home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Libraries / DCLAP 6d / dclap6d / network / entrez / client / netentr.c < prev    next >
Text File  |  1996-07-05  |  70KB  |  2,411 lines

  1. /*   netentr.c
  2. * ===========================================================================
  3. *
  4. *                            PUBLIC DOMAIN NOTICE                          
  5. *               National Center for Biotechnology Information
  6. *                                                                          
  7. *  This software/database is a "United States Government Work" under the   
  8. *  terms of the United States Copyright Act.  It was written as part of    
  9. *  the author's official duties as a United States Government employee and 
  10. *  thus cannot be copyrighted.  This software/database is freely available 
  11. *  to the public for use. The National Library of Medicine and the U.S.    
  12. *  Government have not placed any restriction on its use or reproduction.  
  13. *                                                                          
  14. *  Although all reasonable efforts have been taken to ensure the accuracy  
  15. *  and reliability of the software and data, the NLM and the U.S.          
  16. *  Government do not and cannot warrant the performance or results that    
  17. *  may be obtained by using this software or data. The NLM and the U.S.    
  18. *  Government disclaim all warranties, express or implied, including       
  19. *  warranties of performance, merchantability or fitness for any particular
  20. *  purpose.                                                                
  21. *                                                                          
  22. *  Please cite the author in any work or product based on this material.   
  23. *
  24. * ===========================================================================
  25. *
  26. * File Name:  netentr.c
  27. *
  28. * Author:  Ostell, Kans, Epstein
  29. *
  30. * Version Creation Date:   06/02/92
  31. *
  32. * $Revision: 4.0 $
  33. *
  34. * File Description: 
  35. *       entrez index access library for Network Entrez
  36. *
  37. * Modifications:  
  38. * --------------------------------------------------------------------------
  39. * Date     Name        Description of modification
  40. * -------  ----------  -----------------------------------------------------
  41. * 06-08-93 Schuler     Changed datatype for Monitor from Handle to MonitorPtr
  42. *
  43. * 8-16-94  Brylawski   Added routines to access medline term explosion,
  44. *                      mesh tree browsing, and on-the-fly neighboring.
  45. *                       
  46. * 11-20-94 Brylawski   Modifed on-the-fly neighboring to permit the client
  47. *                      to pass more information about user preferences.
  48. *
  49. * ==========================================================================
  50. *
  51. *
  52. * RCS Modification History:
  53. * $Log: netentr.c,v $
  54.  * Revision 4.0  1995/07/26  13:54:59  ostell
  55.  * force revision to 4.0
  56.  *
  57.  * Revision 1.48  1995/07/11  14:51:50  epstein
  58.  * fix-up for new docsum implementation
  59.  *
  60.  * Revision 1.47  1995/06/29  16:36:28  epstein
  61.  * add biostruc-complexity, and use new biostrucX ASN.1 construct to communicate with server
  62.  *
  63.  * Revision 1.46  95/06/07  16:10:50  epstein
  64.  * add return value to SwapInEntrez()
  65.  * 
  66.  * Revision 1.45  95/06/07  15:47:27  epstein
  67.  * make BLAST search cancellable in conjunction with Monitor
  68.  * 
  69.  * Revision 1.44  95/05/17  17:53:08  epstein
  70.  * add RCS log revision history
  71.  * 
  72. */
  73.  
  74. #include <accentr.h>
  75. #include <ncbinet.h>
  76. #include <netentr.h>
  77. #include <netlib.h>
  78. #include <netpriv.h>
  79. #include <objneten.h>
  80.  
  81. typedef struct namedItem {
  82.     Boolean   knownToServer;
  83.     CharPtr   term;
  84.     Char      tmpFileName[PATH_MAX];
  85.     DocType   type;
  86.     DocField  field;
  87. } NamedItem, PNTR NamedItemPtr;
  88.  
  89. static void NEAR s_NetEntrezFini PROTO((void));
  90. static ByteStorePtr NEAR s_NetEntTLEvalX PROTO((ValNodePtr elst));
  91. static Int2 NEAR s_NetDocSumListGet PROTO((DocSumPtr PNTR result, Int2 numuid, DocType type, DocUidPtr uids, Int2 defer_count));
  92. static Int2 NEAR s_NetLinkUidList PROTO((LinkSetPtr PNTR result, DocType type, DocType link_to_type, Int2 numuid, DocUidPtr uids, Boolean mark_missing));
  93. static LinkSetPtr NEAR s_NetUidLinks PROTO((DocType type, DocUid uid, DocType link_to_type));
  94. static Int2 NEAR s_NetTermListByTerm PROTO((DocType type, DocField field, CharPtr term, Int2 numterms, TermListProc proc, Int2Ptr first_page));
  95. static Int2 NEAR s_NetTermListByPage PROTO((DocType type, DocField field, Int2 page, Int2 numpage, TermListProc proc));
  96. static Boolean NEAR s_NetEntrezFindTerm PROTO((DocType type, DocField field, CharPtr term, Int4Ptr spcl, Int4Ptr totl));
  97. static void NEAR s_NetEntrezCreateNamedUidList PROTO((CharPtr term, DocType type, DocField field, Int4 num, DocUidPtr uids));
  98. static Int2 NEAR s_NetEntSeqEntryListGet PROTO((SeqEntryPtr PNTR result, Int2 numuid, DocUidPtr uids, Int2 retcode, Boolean mark_missing));
  99. static
  100. Int2 NEAR s_NetEntMedlineEntryListGet PROTO((MedlineEntryPtr PNTR result, Int2 numuid, DocUidPtr uids, Boolean mark_missing));
  101.  
  102. static NamedListPtr KnownNamedTerm PROTO((CharPtr term, Boolean onlyIfNotKnown, DocType type, DocField field));
  103. static void CleanupNamedUidLists PROTO((void));
  104. static AsnTypePtr NetEntReadAsn PROTO((void));
  105. static Boolean ReestablishNetEntrez PROTO((void));
  106. static Boolean SwapInEntrez PROTO((VoidPtr med));
  107. static void countChars PROTO((CharPtr str));
  108. static CharPtr SkipSpaces(CharPtr str);
  109.  
  110. static NI_HandPtr Entrez_ni = NULL;
  111. static AsnIoPtr   Entrez_asnin = NULL;
  112. static AsnIoPtr   Entrez_asnout = NULL;
  113. static EntrezInfoPtr vi = NULL;
  114. static CharPtr    infoBuf = NULL;
  115. static size_t     charCount = 0;
  116. static ValNodePtr namedTerms = NULL;
  117. static CharPtr    netEntrezVersion = "2.02b2";
  118. static CharPtr    userApplId = NULL;
  119. static Boolean    userWarnings;
  120. static EntrezExtraInfoPtr eeip = NULL;
  121.  
  122. static AsnTypePtr ENTREZ_BACK = NULL;
  123. static AsnTypePtr ENTREZ_BACK_blast_bad_count = NULL;
  124. static AsnTypePtr ENTREZ_BACK_blast_job_progress = NULL;
  125. static AsnTypePtr ENTREZ_BACK_blast_job_start = NULL;
  126. static AsnTypePtr ENTREZ_BACK_blast_link_set = NULL;
  127. static AsnTypePtr ENTREZ_BACK_docsumX = NULL;
  128. static AsnTypePtr ENTREZ_BACK_error = NULL;
  129. static AsnTypePtr ENTREZ_BACK_evalX = NULL;
  130. static AsnTypePtr ENTREZ_BACK_eval_count = NULL;
  131. static AsnTypePtr ENTREZ_BACK_extrainfo = NULL;
  132. static AsnTypePtr ENTREZ_BACK_get_hierarchy = NULL;
  133. static AsnTypePtr ENTREZ_BACK_init = NULL;
  134. static AsnTypePtr ENTREZ_BACK_init_e_info = NULL;
  135. static AsnTypePtr ENTREZ_BACK_neighbortext = NULL;
  136. static AsnTypePtr ENTREZ_REQUEST = NULL;
  137. static AsnTypePtr ENTREZ_REQUEST_blast = NULL;
  138. static AsnTypePtr ENTREZ_REQUEST_bypage = NULL;
  139. static AsnTypePtr ENTREZ_REQUEST_byterm = NULL;
  140. static AsnTypePtr ENTREZ_REQUEST_createnamed = NULL;
  141. static AsnTypePtr ENTREZ_REQUEST_docsumX = NULL;
  142. static AsnTypePtr ENTREZ_REQUEST_evalX = NULL;
  143. static AsnTypePtr ENTREZ_REQUEST_eval_count = NULL;
  144. static AsnTypePtr ENTREZ_REQUEST_extrainfo = NULL;
  145. static AsnTypePtr ENTREZ_REQUEST_findseqid = NULL;
  146. static AsnTypePtr ENTREZ_REQUEST_findterm = NULL;
  147. static AsnTypePtr ENTREZ_REQUEST_fini = NULL;
  148. static AsnTypePtr ENTREZ_REQUEST_get_hierarchy = NULL;
  149. static AsnTypePtr ENTREZ_REQUEST_getbiostr = NULL;
  150. static AsnTypePtr ENTREZ_REQUEST_getbiostrX = NULL;
  151. static AsnTypePtr ENTREZ_REQUEST_getbiostrX_get = NULL;
  152. static AsnTypePtr REQUEST_getbiostrX_complexity = NULL;
  153. static AsnTypePtr ENTREZ_REQUEST_getmle = NULL;
  154. static AsnTypePtr ENTREZ_REQUEST_getseq = NULL;
  155. static AsnTypePtr ENTREZ_REQUEST_initX = NULL;
  156. static AsnTypePtr ENTREZ_REQUEST_initX_version = NULL;
  157. static AsnTypePtr ENTREZ_REQUEST_linkuidlist = NULL;
  158. static AsnTypePtr ENTREZ_REQUEST_neighbortext = NULL;
  159. static AsnTypePtr ENTREZ_REQUEST_seqidforgi = NULL;
  160. static AsnTypePtr ENTREZ_REQUEST_uidlinks = NULL;
  161. static AsnTypePtr ENTREZ_TERMGET_cls = NULL;
  162. static AsnTypePtr ENTREZ_TERMGET_terms = NULL;
  163.  
  164. extern EntrezInfoPtr LIBCALL EntrezInfoAsnRead PROTO((AsnIoPtr aip, AsnTypePtr atp));
  165. EntrezInfoPtr NetEntrezGetInfo PROTO((void));
  166. static void RemoveNonPrintingCharacters(CharPtr str);
  167. static CharPtr SkipSpaces(CharPtr str);
  168.  
  169.  
  170. static void NEAR FindAsnType (AsnTypePtr PNTR atp, AsnModulePtr amp, CharPtr str)
  171.  
  172. {
  173.   if (atp != NULL && (*atp) == NULL) {
  174.     *atp = AsnTypeFind (amp, str);
  175.   }
  176. }
  177.  
  178.  
  179. /*****************************************************************************
  180. *
  181. *   NetEntrezInit ()
  182. *
  183. *****************************************************************************/
  184.  
  185. Boolean CDECL NetEntrezInit (CharPtr appl_id, Boolean no_warnings)
  186.  
  187. {
  188.     AsnIoPtr   asnin;
  189.     AsnIoPtr   asnout;
  190.     AsnTypePtr atp;
  191.     MediaPtr   media;
  192.     DataVal    av;
  193.     CharPtr    versionId;
  194.     AsnModulePtr amp;
  195.  
  196.     NetEntAsnLoad();
  197.     amp = AsnAllModPtr();
  198.  
  199.     FindAsnType(&ENTREZ_BACK, amp, "Entrez-back");
  200.     FindAsnType(&ENTREZ_BACK_blast_bad_count, amp, "Entrez-back.blast.bad-count");
  201.     FindAsnType(&ENTREZ_BACK_blast_job_progress, amp, "Entrez-back.blast.job-progress");
  202.     FindAsnType(&ENTREZ_BACK_blast_job_start, amp, "Entrez-back.blast.job-start");
  203.     FindAsnType(&ENTREZ_BACK_blast_link_set, amp, "Entrez-back.blast.link-set");
  204.     FindAsnType(&ENTREZ_BACK_docsumX, amp, "Entrez-back.docsumX");
  205.     FindAsnType(&ENTREZ_BACK_error, amp, "Entrez-back.error");
  206.     FindAsnType(&ENTREZ_BACK_evalX, amp, "Entrez-back.evalX");
  207.     FindAsnType(&ENTREZ_BACK_eval_count, amp, "Entrez-back.eval-count");
  208.     FindAsnType(&ENTREZ_BACK_extrainfo, amp, "Entrez-back.extrainfo");
  209.     FindAsnType(&ENTREZ_BACK_get_hierarchy, amp, "Entrez-back.get-hierarchy");
  210.     FindAsnType(&ENTREZ_BACK_init, amp, "Entrez-back.init");
  211.     FindAsnType(&ENTREZ_BACK_init_e_info, amp, "Entrez-back.init.e-info");
  212.     FindAsnType(&ENTREZ_BACK_neighbortext, amp, "Entrez-back.neighbortext");
  213.     FindAsnType(&ENTREZ_REQUEST, amp, "Entrez-request");
  214.     FindAsnType(&ENTREZ_REQUEST_blast, amp, "Entrez-request.blast");
  215.     FindAsnType(&ENTREZ_REQUEST_bypage, amp, "Entrez-request.bypage");
  216.     FindAsnType(&ENTREZ_REQUEST_byterm, amp, "Entrez-request.byterm");
  217.     FindAsnType(&ENTREZ_REQUEST_createnamed, amp, "Entrez-request.createnamed");
  218.     FindAsnType(&ENTREZ_REQUEST_docsumX, amp, "Entrez-request.docsumX");
  219.     FindAsnType(&ENTREZ_REQUEST_evalX, amp, "Entrez-request.evalX");
  220.     FindAsnType(&ENTREZ_REQUEST_eval_count, amp, "Entrez-request.eval-count");
  221.     FindAsnType(&ENTREZ_REQUEST_extrainfo, amp, "Entrez-request.extrainfo");
  222.     FindAsnType(&ENTREZ_REQUEST_findseqid, amp, "Entrez-request.findseqid");
  223.     FindAsnType(&ENTREZ_REQUEST_findterm, amp, "Entrez-request.findterm");
  224.     FindAsnType(&ENTREZ_REQUEST_fini, amp, "Entrez-request.fini");
  225.     FindAsnType(&ENTREZ_REQUEST_get_hierarchy, amp, "Entrez-request.get-hierarchy");
  226.     FindAsnType(&ENTREZ_REQUEST_getbiostr, amp, "Entrez-request.getbiostr");
  227.     FindAsnType(&ENTREZ_REQUEST_getbiostrX, amp, "Entrez-request.getbiostrX");
  228.     FindAsnType(&REQUEST_getbiostrX_complexity, amp, "Entrez-request.getbiostrX.complexity");
  229.     FindAsnType(&ENTREZ_REQUEST_getbiostrX_get, amp, "Entrez-request.getbiostrX.get");
  230.     FindAsnType(&ENTREZ_REQUEST_getmle, amp, "Entrez-request.getmle");
  231.     FindAsnType(&ENTREZ_REQUEST_getseq, amp, "Entrez-request.getseq");
  232.     FindAsnType(&ENTREZ_REQUEST_initX, amp, "Entrez-request.initX");
  233.     FindAsnType(&ENTREZ_REQUEST_initX_version, amp, "Entrez-request.initX.version");
  234.     FindAsnType(&ENTREZ_REQUEST_linkuidlist, amp, "Entrez-request.linkuidlist");
  235.     FindAsnType(&ENTREZ_REQUEST_neighbortext, amp, "Entrez-request.neighbortext");
  236.     FindAsnType(&ENTREZ_REQUEST_seqidforgi, amp, "Entrez-request.seqidforgi");
  237.     FindAsnType(&ENTREZ_REQUEST_uidlinks, amp, "Entrez-request.uidlinks");
  238.     FindAsnType(&ENTREZ_TERMGET_cls, amp, "Entrez-termget.cls");
  239.     FindAsnType(&ENTREZ_TERMGET_terms, amp, "Entrez-termget.terms");
  240.  
  241.     if (! NetInit())
  242.         return FALSE;
  243.  
  244.     userWarnings = no_warnings;
  245.  
  246.     Entrez_ni = NetServiceGet("ENTR_LINK", "Entrez", SwapInEntrez, Entrez_ni);
  247.     if (Entrez_ni == NULL)
  248.     {
  249.         Message(MSG_ERROR, "NI_ServiceGet [%s] (%s)", ni_errlist[ni_errno], ni_errtext);
  250.         Entrez_asnin = NULL;
  251.         Entrez_asnout = NULL;
  252.         NetEntrezFini();
  253.         return FALSE;
  254.     }
  255.  
  256.     asnin = Entrez_ni->raip;
  257.     asnout = Entrez_ni->waip;
  258.  
  259.     Entrez_asnin = asnin;
  260.     Entrez_asnout = asnout;
  261.  
  262.     /* don't get upset if non-printing chars are encountered */
  263.     asnin->fix_non_print = 1;
  264.  
  265.     /**********************************************************/
  266.  
  267.     AsnWrite(asnout, ENTREZ_REQUEST, NULL);
  268.     AsnStartStruct(asnout, ENTREZ_REQUEST_initX);
  269.     if (netEntrezVersion != NULL) {
  270.         if (appl_id == NULL) {
  271.             av.ptrvalue = netEntrezVersion;
  272.             AsnWrite(asnout, ENTREZ_REQUEST_initX_version, &av);
  273.         } else {
  274.             versionId = MemNew(StrLen(netEntrezVersion) + StrLen(appl_id) + 4);
  275.             sprintf (versionId, "%s (%s)", netEntrezVersion, appl_id);
  276.             userApplId = StringSave(appl_id);
  277.             av.ptrvalue = versionId;
  278.             AsnWrite(asnout, ENTREZ_REQUEST_initX_version, &av);
  279.             MemFree (versionId);
  280.         }
  281.     }
  282.     AsnEndStruct(asnout, ENTREZ_REQUEST_initX);
  283.     AsnIoReset(asnout);
  284.  
  285.  
  286.     if ((atp = NetEntReadAsn()) == NULL)
  287.     {
  288.         return FALSE;
  289.     }
  290.     else
  291.     {
  292.         AsnReadVal(asnin, atp, NULL);   /* read the NULL */
  293.         atp = AsnReadId(asnin, amp, atp);
  294.         if (atp == ENTREZ_BACK_init_e_info)
  295.         {
  296.             if (vi != NULL)
  297.             {
  298.                 EntrezInfoFree (vi);
  299.                 vi = NULL;
  300.             }
  301.             vi = EntrezInfoAsnRead(asnin, atp);
  302.             if ((media = GetCurMedia()) != NULL &&
  303.                 media->media_type == MEDIUM_NETWORK)
  304.             {
  305.                 media->entrez_info = vi;
  306.             }
  307.             atp = AsnReadId(asnin, amp, atp);
  308.         }
  309.         if (atp != ENTREZ_BACK_init)
  310.             return FALSE;
  311.         AsnReadVal(asnin, atp, NULL);   /* read the NULL */
  312.         ConfigInit();
  313.         return  TRUE;
  314.     }
  315. }
  316.  
  317. /*****************************************************************************
  318. *
  319. *   NetEntrezFini ()
  320. *
  321. *****************************************************************************/
  322.  
  323. static void NEAR s_NetEntrezFini (void)
  324.  
  325. {
  326.     AsnTypePtr atp;
  327.     AsnIoPtr asnout = Entrez_asnout;
  328.     AsnIoPtr asnin = Entrez_asnin;
  329.  
  330.     if (asnout != NULL && asnin != NULL)
  331.     {
  332.         AsnWrite(asnout, ENTREZ_REQUEST, NULL);
  333.         AsnWrite(asnout, ENTREZ_REQUEST_fini, NULL);
  334.         AsnIoReset(asnout);
  335.  
  336.         if ((atp = NetEntReadAsn()) != NULL)
  337.             AsnReadVal(asnin, atp, NULL);   /* read the NULL */
  338.     }
  339.  
  340.     if (infoBuf != NULL)
  341.     {
  342.         MemFree(infoBuf);
  343.         infoBuf = NULL;
  344.     }
  345.  
  346.     if (userApplId != NULL)
  347.     {
  348.         MemFree(userApplId);
  349.         userApplId = NULL;
  350.     }
  351.     if (eeip != NULL)
  352.     {
  353.         EntrezExtraInfoFree(eeip);
  354.         eeip = NULL;
  355.     }
  356.  
  357.     NI_ServiceDisconnect(Entrez_ni);
  358.     NetFini();
  359.     ConfigFini();
  360. }
  361.  
  362. /* the only thing done here is to suppress errors */
  363. void CDECL NetEntrezFini (void)
  364.  
  365. {
  366.     short erract;
  367.     ErrDesc err;
  368.  
  369.     ErrGetOpts(&erract, NULL);
  370.     ErrSetOpts(ERR_CONTINUE, 0);
  371.     ErrFetch(&err);
  372.  
  373.     s_NetEntrezFini();
  374.  
  375.     ErrSetOpts(erract, 0);
  376.     ErrFetch(&err);
  377.  
  378.     CleanupNamedUidLists ();
  379. }
  380.  
  381. /*****************************************************************************
  382. *
  383. *   NetEntrezGetInfo()
  384. *       returns global Entrez information
  385. *
  386. *****************************************************************************/
  387. EntrezInfoPtr CDECL
  388. NetEntrezGetInfo(void)
  389. {
  390.     return vi;
  391. }
  392.  
  393. /*****************************************************************************
  394. *
  395. *   NetEntrezDetailedInfo()
  396. *       returns NULL, or a string to some descriptive text
  397. *
  398. *****************************************************************************/
  399. CharPtr CDECL
  400. NetEntrezDetailedInfo(void)
  401. {
  402.     charCount = 0;
  403.     DumpNetStats(SUBSYS_CLI_ENTREZ, countChars);
  404.  
  405.     if (infoBuf != NULL)
  406.         MemFree(infoBuf);
  407.     infoBuf = MemNew(charCount + 540);
  408.     GetClientInfo(infoBuf);
  409.     return infoBuf;
  410. }
  411.  
  412. static EntrezExtraInfoPtr
  413. GetEntrezExtraInfo(void)
  414. {
  415.     AsnTypePtr atp;
  416.     DataVal av;
  417.  
  418.     if (eeip == NULL && Entrez_asnout != NULL)
  419.     {
  420.         AsnWrite(Entrez_asnout, ENTREZ_REQUEST, NULL);
  421.         av.intvalue = 4; /* number of currently known fields */
  422.         AsnWrite(Entrez_asnout, ENTREZ_REQUEST_extrainfo, &av);
  423.         AsnIoReset(Entrez_asnout);
  424.         if ((atp = NetEntReadAsn()) != NULL)
  425.             eeip = EntrezExtraInfoAsnRead(Entrez_asnin, ENTREZ_BACK_extrainfo);
  426.     }
  427.  
  428.     return eeip;
  429. }
  430.  
  431. /*****************************************************************************
  432. *
  433. *   NetEntGetMaxLinks()
  434. *       returns max links in link set allowed by system
  435. *
  436. *****************************************************************************/
  437.  
  438. Int4 NetEntGetMaxLinks(void)
  439. {
  440.     EntrezExtraInfoPtr myeeip;
  441.  
  442.     if ((myeeip = GetEntrezExtraInfo()) == NULL)
  443.     {
  444.         return -1;
  445.     }
  446.  
  447.     return myeeip->maxlinks;
  448. }
  449.  
  450. /*****************************************************************************
  451. *
  452. *   NetEntTLNew ()
  453. *
  454. *****************************************************************************/
  455.  
  456. ValNodePtr CDECL NetEntTLNew (DocType type)
  457.  
  458. {
  459.   ValNodePtr anp;
  460.  
  461.   anp = ValNodeNew(NULL);
  462.   anp->data.intvalue = (Int4)type;
  463.   return anp;
  464. }
  465.  
  466. /*****************************************************************************
  467. *
  468. *   NetEntTLAddTerm (elst, term, type, field, special)
  469. *       Adds a term node to a boolean algebraic term query.
  470. *
  471. *****************************************************************************/
  472.  
  473. ValNodePtr CDECL NetEntTLAddTerm(ValNodePtr elst, CharPtr term, DocType type,
  474.                                   DocField field, Boolean special)
  475.  
  476. {
  477.     ValNodePtr anp;
  478.     TermDataPtr termdatp;
  479.     NamedListPtr nlp;
  480.   
  481.     anp = NULL;
  482.     if (elst != NULL) {
  483.         if (elst->data.intvalue != (Int4)type)
  484.             return NULL;
  485.         anp = ValNodeNew (elst);
  486.         if (anp != NULL) {
  487.             if ((nlp = KnownNamedTerm(term, TRUE, type, field)) != NULL &&
  488.                 nlp->uids != NULL) {
  489.                 NetEntrezCreateNamedUidList (term, type, field, nlp->uids->numid,
  490.                                              nlp->uids->ids);
  491.             }
  492.   
  493.             if (special) {
  494.                 anp->choice = SPECIALTERM;
  495.             } else {
  496.                 anp->choice = TOTALTERM;
  497.             }
  498.   
  499.             termdatp = (TermDataPtr) MemNew(sizeof(TermData));
  500.             termdatp->field = field;
  501.             termdatp->type = type;
  502.             termdatp->term = StringSave(term);
  503.             anp->data.ptrvalue = (Pointer) termdatp;
  504.         }
  505.     }
  506.     LOG_STAT(SUBSYS_CLI_ENTREZ, "Boolean terms", 1);
  507.     return anp;
  508. }
  509.  
  510. /*****************************************************************************
  511. *
  512. *   NetEntTLFree (elst)
  513. *       Frees a boolean algebraic term query list.
  514. *
  515. *****************************************************************************/
  516.  
  517. ValNodePtr CDECL NetEntTLFree (ValNodePtr elst)
  518.  
  519. {
  520.     ValNodePtr anp;
  521.     TermDataPtr trmp;
  522.  
  523.     if (elst != NULL) {
  524.         elst->data.intvalue = 0;   /* clear type */
  525.         for (anp = elst->next; anp != NULL; anp = anp->next) {
  526.             if (anp->choice == SPECIALTERM || anp->choice == TOTALTERM) {
  527.                 trmp = (TermDataPtr) anp->data.ptrvalue;
  528.                 MemFree (trmp->term);
  529.                 trmp->term = NULL;
  530.             }
  531.         }
  532.         ValNodeFreeData (elst);
  533.     }
  534.     return NULL;
  535. }
  536.  
  537. /*****************************************************************************
  538. *
  539. *   NetEntTLEval (elst)
  540. *       Evaluates a boolean algebraic term query list, returning a pointer to
  541. *       a LinkSetPtr containing the resultant unique identifiers.
  542. *
  543. *****************************************************************************/
  544.  
  545.  
  546. LinkSetPtr CDECL NetEntTLEval (ValNodePtr elst)
  547.  
  548. {
  549.     ByteStorePtr bsp;
  550.     LinkSetPtr lsp;
  551.     Int4 numlinks;
  552.  
  553.     if ((bsp = NetEntTLEvalX(elst)) != NULL)
  554.     {
  555.         numlinks = BSLen(bsp) / sizeof(DocUid);
  556.         lsp = LinkSetNew();
  557.         lsp->num = numlinks;
  558.         if (numlinks <= EntrezGetUserMaxLinks())
  559.         {
  560.                 lsp->uids = MemNew((size_t)(numlinks * sizeof(DocUid)));                        BSSeek (bsp, 0L, 0);
  561.                 BSRead(bsp, lsp->uids, (numlinks * sizeof(DocUid)));
  562.         }
  563.         BSFree(bsp);
  564.     }
  565.     return lsp;
  566.  
  567. }
  568.  
  569.  
  570. #ifdef IS_BIG_ENDIAN
  571. /* no swapping needed:  define do-nothing macros */
  572. #define SwapInt4(X)  (X)
  573. #else
  574. /* give prototypes for byte swapping functions */
  575. static Int4 NEAR  SwapInt4  PROTO((Int4));
  576. #endif
  577.  
  578. #ifdef IS_LITTLE_ENDIAN
  579.  
  580. static Int4 NEAR  SwapInt4 (Int4 k)
  581.  
  582. {
  583.     Uint4  j, l;
  584.     Int4 m;
  585.  
  586.     l = (Uint4)k;
  587.     j  = ((l & (Uint4)0xFF000000) >> 24);
  588.     j |= ((l & (Uint4)0x00FF0000) >> 8);
  589.     j |= ((l & (Uint4)0x0000FF00) << 8);
  590.     j |= ((l & (Uint4)0x000000FF) << 24);
  591.     m = (Int4)j;
  592.     return  m;
  593. }
  594.  
  595. #endif
  596.  
  597.  
  598. /*****************************************************************************
  599. *
  600. *   NetEntTLEvalX (elst)
  601. *       Evaluates a boolean algebraic term query list, returning a pointer to
  602. *       a ByteStore containing the resultant unique identifiers.
  603. *
  604. *****************************************************************************/
  605.  
  606. static ByteStorePtr NEAR s_NetEntTLEvalX (ValNodePtr elst)
  607.  
  608. {
  609.     ByteStorePtr bsp = NULL;
  610.     AsnTypePtr atp;
  611.     DataVal av;
  612.  
  613.     if (elst == NULL)
  614.         return NULL;
  615.     if (elst->next == NULL) /* expression without terms */
  616.         return NULL;
  617.     AsnWrite(Entrez_asnout, ENTREZ_REQUEST, NULL);
  618.     AsnStartStruct(Entrez_asnout, ENTREZ_REQUEST_evalX);
  619.     av.intvalue = elst->data.intvalue;
  620.     AsnWrite(Entrez_asnout, ENTREZ_TERMGET_cls, &av);
  621.     BoolExprAsnWrite (elst->next, Entrez_asnout, ENTREZ_TERMGET_terms);
  622.     AsnEndStruct(Entrez_asnout, ENTREZ_REQUEST_evalX);
  623.     AsnIoReset(Entrez_asnout);
  624.  
  625.     if ((atp = NetEntReadAsn()) == NULL)
  626.         return NULL;
  627.  
  628.     if (atp == ENTREZ_BACK_evalX)
  629.     {
  630.         AsnReadVal(Entrez_asnin, atp, &av);
  631.         bsp = (ByteStorePtr) av.ptrvalue;
  632. #ifdef IS_LITTLE_ENDIAN
  633.         {
  634.             Int4 datum;
  635.             Int4 offset;
  636.             Int4 i;
  637.  
  638.             for (i = BSLen(bsp) / sizeof(Int4), offset = 0; i > 0;
  639.                  i--, offset += sizeof(Int4))
  640.             {
  641.                 BSSeek(bsp, offset, SEEK_SET);
  642.                 BSRead(bsp, &datum, sizeof(Int4));
  643.                 datum = SwapInt4(datum);
  644.                 BSSeek(bsp, offset, SEEK_SET);
  645.                 BSWrite(bsp, &datum, sizeof(Int4));
  646.             }
  647.         }
  648. #endif /* IS_LITTLE_ENDIAN */
  649.     }
  650.     LOG_STAT(SUBSYS_CLI_ENTREZ, "Boolean expressions evaluated", 1);
  651.     LOG_STAT(SUBSYS_CLI_ENTREZ, "Resulting UIDs from Boolean evaluation", bsp == NULL ? 0 : BSLen(bsp) / sizeof(DocUid));
  652.     return bsp;
  653. }
  654.  
  655. ByteStorePtr CDECL NetEntTLEvalX (ValNodePtr elst)
  656.  
  657. {
  658.     int i;
  659.     ByteStorePtr retval;
  660.     short erract;
  661.     ErrDesc err;
  662.  
  663.     for (i = 0; i < ENT_SERV_RETRIES; i++)
  664.     {
  665.         if (i > 0)
  666.         {
  667.             if (! ReestablishNetEntrez())
  668.                 break;
  669.         }
  670.  
  671.         ErrGetOpts(&erract, NULL);
  672.         ErrSetOpts(ERR_CONTINUE, 0);
  673.         ErrFetch(&err);
  674.         retval = s_NetEntTLEvalX(elst);
  675.         ErrSetOpts(erract, 0);
  676.         if (! ErrFetch(&err))
  677.             return retval; /* success */
  678.     }
  679.  
  680.     ErrPost(CTX_UNKNOWN, 1, "NetEntTLEval failure");
  681.     return NULL;
  682. }
  683.  
  684. /*****************************************************************************
  685. *
  686. *   NetEntTLEvalCount (elst)
  687. *       Evaluates a boolean algebraic term query list, returning a count of
  688. *       the resultant unique identifiers.
  689. *
  690. *****************************************************************************/
  691.  
  692. static Int4 NEAR s_NetEntTLEvalCount (ValNodePtr elst)
  693.  
  694. {
  695.     Int4 retval = 0;
  696.     AsnTypePtr atp;
  697.     DataVal av;
  698.  
  699.     if (elst->next == NULL) /* expression without terms */
  700.         return 0;
  701.     AsnWrite(Entrez_asnout, ENTREZ_REQUEST, NULL);
  702.     AsnStartStruct(Entrez_asnout, ENTREZ_REQUEST_eval_count);
  703.     av.intvalue = elst->data.intvalue;
  704.     AsnWrite(Entrez_asnout, ENTREZ_TERMGET_cls, &av);
  705.     BoolExprAsnWrite (elst->next, Entrez_asnout, ENTREZ_TERMGET_terms);
  706.     AsnEndStruct(Entrez_asnout, ENTREZ_REQUEST_eval_count);
  707.     AsnIoReset(Entrez_asnout);
  708.  
  709.     if ((atp = NetEntReadAsn()) == NULL)
  710.         return 0;
  711.  
  712.     if (atp == ENTREZ_BACK_eval_count)
  713.     {
  714.         AsnReadVal(Entrez_asnin, atp, &av);
  715.         retval = (Int4) av.intvalue;
  716.     }
  717.     LOG_STAT(SUBSYS_CLI_ENTREZ, "Boolean expressions counted", 1);
  718.     LOG_STAT(SUBSYS_CLI_ENTREZ, "Resulting UIDs from Boolean count-evaluation", retval);
  719.     return retval;
  720. }
  721.  
  722. Int4 CDECL NetEntTLEvalCount (ValNodePtr elst)
  723.  
  724. {
  725.     int i;
  726.     Int4 retval;
  727.     short erract;
  728.     ErrDesc err;
  729.  
  730.     for (i = 0; i < ENT_SERV_RETRIES; i++)
  731.     {
  732.         if (i > 0)
  733.         {
  734.             if (! ReestablishNetEntrez())
  735.                 break;
  736.         }
  737.  
  738.         ErrGetOpts(&erract, NULL);
  739.         ErrSetOpts(ERR_CONTINUE, 0);
  740.         ErrFetch(&err);
  741.         retval = s_NetEntTLEvalCount(elst);
  742.         ErrSetOpts(erract, 0);
  743.         if (! ErrFetch(&err))
  744.             return retval; /* success */
  745.     }
  746.  
  747.     ErrPost(CTX_UNKNOWN, 1, "NetEntTLEvalCount failure");
  748.     return 0;
  749. }
  750.  
  751.  
  752. /*****************************************************************************
  753. *
  754. *   NetDocSumListGet (result, numuid, type, uids)
  755. *       returns a count of entries read
  756. *       head of linked list is in result
  757. *
  758. *****************************************************************************/
  759. static Int2 NEAR s_NetDocSumListGet (DocSumPtr PNTR result, Int2 numuid,
  760.                                       DocType type, DocUidPtr uids,
  761.                                       Int2 defer_count)
  762.  
  763. {
  764.     DataVal av;
  765.     AsnTypePtr atp;
  766.     EntrezIdsPtr eip;
  767.     Int2 retval;
  768.     EntrezDocGetPtr edgp;
  769.     AsnModulePtr amp;
  770.     NewSummaryListPtr newlist;
  771.  
  772.     NetEntAsnLoad();
  773.     amp = AsnAllModPtr();
  774.  
  775.     AsnWrite(Entrez_asnout, ENTREZ_REQUEST, NULL);
  776.     edgp = EntrezDocGetNew();
  777.     edgp->ids = EntrezIdsNew();
  778.     eip = edgp->ids;
  779.     edgp->cls = type;
  780.     edgp->mark_missing = FALSE;
  781.     eip->numid = numuid;
  782.     eip->ids = uids;
  783.     edgp->defer_count = defer_count;
  784.     EntrezDocGetAsnWrite(edgp, Entrez_asnout, ENTREZ_REQUEST_docsumX);
  785.     eip->ids = NULL; /* for clean memory free */
  786.     EntrezDocGetFree(edgp);
  787.  
  788.     AsnIoReset(Entrez_asnout);
  789.  
  790.     if ((atp = NetEntReadAsn()) == NULL)
  791.         return -1;
  792.  
  793.     newlist = NewSummaryListAsnRead(Entrez_asnin, atp);
  794.     if (newlist == NULL)
  795.     return -1;
  796.     if (newlist->type != type)
  797.     {
  798.     NewSummaryListFree(newlist);
  799.     return -1;
  800.     }
  801.     MemCopy (result, newlist->data, (size_t) newlist->num * sizeof(DocSumPtr));
  802.     retval = newlist->num;
  803.     MemFree(newlist->data);
  804.     newlist->data = NULL; /* to avoid freeing actual DocSums */
  805.     NewSummaryListFree (newlist);
  806.  
  807.     LOG_STAT(SUBSYS_CLI_ENTREZ, "Document summaries retrieved", retval);
  808.     LOG_STAT(SUBSYS_CLI_ENTREZ, "Document summaries requested", numuid);
  809.  
  810.     return retval;
  811. }
  812.  
  813. Int2 CDECL NetDocSumListGet (DocSumPtr PNTR result, Int2 numuid,
  814.                           DocType type, DocUidPtr uids, Int2 defer_count)
  815. {
  816.     int i;
  817.     int retval;
  818.     short erract;
  819.     ErrDesc err;
  820.  
  821.     /* default is to obtain these from the Entrez server */
  822.  
  823.     for (i = 0; i < ENT_SERV_RETRIES; i++)
  824.     {
  825.         if (i > 0)
  826.         {
  827.             if (! ReestablishNetEntrez())
  828.                 break;
  829.         }
  830.  
  831.         ErrGetOpts(&erract, NULL);
  832.         ErrSetOpts(ERR_CONTINUE, 0);
  833.         ErrFetch(&err);
  834.         retval = s_NetDocSumListGet (result, numuid, type, uids, defer_count);
  835.         ErrSetOpts(erract, 0);
  836.         if (! ErrFetch(&err))
  837.         {
  838.             goto expand_uids;
  839.         }
  840.     }
  841.  
  842.     ErrPost(CTX_UNKNOWN, 1, "DocSumGet failure");
  843.     return -1;
  844.  
  845. expand_uids:
  846.     if (retval < 0 || retval == numuid)
  847.         return retval;
  848.  
  849.     {
  850.         Int2 i,j;
  851.         DocSumPtr dsp;
  852. #define USE_TEMP_MEMORY
  853. #ifdef USE_TEMP_MEMORY
  854.         DocSumPtr PNTR temp;
  855.     
  856.         /* some UIDs are missing; we must find which ones and insert NULLs */
  857.         if ((temp = MemNew(sizeof(DocSumPtr) * numuid)) == NULL)
  858.         {
  859.             ErrPost(CTX_UNKNOWN, 1, "DocSumGet failure <memory allocation>");
  860.             return -1;
  861.         }
  862.     
  863.         for (i = 0; i < numuid; i++)
  864.         {
  865.             temp[i] = result[i];
  866.             result[i] = NULL;
  867.         }
  868.  
  869.         for (i = 0, j = 0; i < retval; i++) {
  870.             dsp = temp[i];
  871.             if (dsp != NULL) {
  872.                 while (j < numuid && dsp->uid != uids[j]) {
  873.                     j++;
  874.                 }
  875.                 if (j < numuid) {
  876.                     result[j] = dsp;
  877.                     j++;
  878.                 }
  879.             }
  880.         }
  881.  
  882.         MemFree (temp);
  883. #else
  884.         /* more dangerous algorithm ... operates on result in-place */
  885.         for (i = retval - 1, j = numuid - 1; i >= 0; i--) {
  886.             dsp = result[i];
  887.             if (dsp != NULL) {
  888.                 while (j >= 0 && dsp->uid != uids[j]) {
  889.                     result[j] = NULL;
  890.                     j--;
  891.                 }
  892.                 if (j >= 0)
  893.                 {
  894.                     result[j] = dsp;
  895.                     j--;
  896.                 }
  897.             }
  898.         }
  899.  
  900.         for (; j >= 0; j--)
  901.         { /* null out any unassigned bottom entries */
  902.             result[j] = NULL;
  903.         }
  904. #endif /* USE_TEMP_MEMORY */
  905.  
  906.         return retval;
  907.     }
  908. }
  909.         
  910.  
  911. /*****************************************************************************
  912. *
  913. *   DocSumPtr NetDocSum(type, uid)
  914. *
  915. *****************************************************************************/
  916.  
  917. DocSumPtr CDECL NetDocSum (DocType type, DocUid uid)
  918. {
  919.     DocSumPtr dsp = NULL;
  920.  
  921.     NetDocSumListGet(&dsp, 1, type, &uid, 0);
  922.     return dsp;
  923. }
  924.  
  925. /*****************************************************************************
  926. *
  927. *   NetLinkUidList(type, link_to_type, numuid, uids)
  928. *       returns count of input uids processed
  929. *       returns -1 on error
  930. *       if neighbors (type == link_to_type)
  931. *           sums weights for same uids
  932. *       if (more than EntrezUserMaxLinks() uids, frees uids and weights,
  933. *           but leaves num set)
  934. *
  935. *****************************************************************************/
  936. static
  937. Int2 NEAR s_NetLinkUidList (LinkSetPtr PNTR result, DocType type,
  938.                               DocType   link_to_type, Int2 numuid, DocUidPtr uids,
  939.                               Boolean mark_missing)
  940.  
  941. {
  942.     LinkSetGetPtr lsgp;
  943.     MarkedLinkSetPtr mls;
  944.     AsnTypePtr atp;
  945.     Int2 retval;
  946.  
  947.     lsgp = LinkSetGetNew();
  948.     lsgp->query_cls = type;
  949.     lsgp->link_to_cls = link_to_type;
  950.     lsgp->max = EntrezGetUserMaxLinks();
  951.     lsgp->mark_missing = mark_missing;
  952.     lsgp->query_size = numuid;
  953.     lsgp->query = MemNew(sizeof(DocUid) * numuid);
  954.  
  955.     MemCopy (lsgp->query, uids, sizeof(DocUid) * numuid);
  956.     AsnWrite(Entrez_asnout, ENTREZ_REQUEST, NULL);
  957.     LinkSetGetAsnWrite(lsgp, Entrez_asnout, ENTREZ_REQUEST_linkuidlist);
  958.     AsnIoReset(Entrez_asnout);
  959.  
  960.     LinkSetGetFree (lsgp);
  961.  
  962.     if ((atp = NetEntReadAsn()) == NULL)
  963.         return -1;
  964.     if ((mls = MarkedLinkSetAsnRead(Entrez_asnin, atp)) == NULL)
  965.         return -1;
  966.     *result = mls->link_set;
  967.     retval = mls->uids_processed;
  968.     if (mark_missing && mls->marked_missing != NULL)
  969.         MemCopy (uids, mls->marked_missing->ids, numuid * sizeof(DocUid));
  970.     mls->link_set = NULL; /* for clean memory free */
  971.     MarkedLinkSetFree (mls);
  972.  
  973.     LOG_STAT(SUBSYS_CLI_ENTREZ, "UID attempted for neighbors", numuid);
  974.     LOG_STAT(SUBSYS_CLI_ENTREZ, "UID processed for neighbors", retval);
  975.     LOG_STAT(SUBSYS_CLI_ENTREZ, "UID neighbors found", *result == NULL ? 0 : (*result)->num);
  976.     return retval;
  977. }
  978.  
  979. Int2 CDECL NetLinkUidList (LinkSetPtr PNTR result, DocType type,
  980.                             DocType link_to_type, Int2 numuid, DocUidPtr uids,
  981.                             Boolean mark_missing)
  982. {
  983.     int i;
  984.     int retval;
  985.     short erract;
  986.     ErrDesc err;
  987.     DocUidPtr local_uids;
  988.  
  989.     /* make a local copy, to handle modifications */
  990.     local_uids = MemNew(sizeof(DocUid) * numuid);
  991.  
  992.     for (i = 0; i < ENT_SERV_RETRIES; i++)
  993.     {
  994.         MemCopy(local_uids, uids, sizeof(DocUid) * numuid);
  995.         if (i > 0)
  996.         {
  997.             if (! ReestablishNetEntrez())
  998.                 break;
  999.         }
  1000.  
  1001.         ErrGetOpts(&erract, NULL);
  1002.         ErrSetOpts(ERR_CONTINUE, 0);
  1003.         ErrFetch(&err);
  1004.         retval = s_NetLinkUidList(result, type, link_to_type, numuid,
  1005.                       local_uids, mark_missing);
  1006.         ErrSetOpts(erract, 0);
  1007.         if (! ErrFetch(&err))
  1008.         {
  1009.             MemCopy(uids, local_uids, sizeof(DocUid) * numuid);
  1010.             MemFree(local_uids);
  1011.             return retval; /* success */
  1012.         }
  1013.     }
  1014.  
  1015.     MemFree(local_uids);
  1016.     ErrPost(CTX_UNKNOWN, 1, "NetLinkUidList failure");
  1017.     return -1;
  1018. }
  1019.  
  1020. /*****************************************************************************
  1021. *
  1022. *   NetUidLinks()
  1023. *       retrieves links to other uids
  1024. *
  1025. *****************************************************************************/
  1026. static
  1027. LinkSetPtr NEAR s_NetUidLinks(DocType type, DocUid uid, DocType link_to_type)
  1028.  
  1029. {
  1030.     LinkSetPtr lsp;
  1031.     LinkSetGetPtr lsgp;
  1032.     MarkedLinkSetPtr mls;
  1033.     AsnTypePtr atp;
  1034.  
  1035.     lsgp = LinkSetGetNew();
  1036.     lsgp->query_cls = type;
  1037.     lsgp->link_to_cls = link_to_type;
  1038.     lsgp->max = EntrezGetUserMaxLinks();
  1039.     lsgp->mark_missing = FALSE;
  1040.     lsgp->query_size = 1;
  1041.     lsgp->query = MemNew(sizeof(DocUid));
  1042.     lsgp->query[0] = uid;
  1043.  
  1044.     AsnWrite(Entrez_asnout, ENTREZ_REQUEST, NULL);
  1045.     LinkSetGetAsnWrite(lsgp, Entrez_asnout, ENTREZ_REQUEST_uidlinks);
  1046.     AsnIoReset(Entrez_asnout);
  1047.  
  1048.     LinkSetGetFree (lsgp);
  1049.  
  1050.     if ((atp = NetEntReadAsn()) == NULL)
  1051.         return NULL;
  1052.     if ((mls = MarkedLinkSetAsnRead(Entrez_asnin, atp)) == NULL)
  1053.         return NULL;
  1054.     lsp = mls->link_set;
  1055.     mls->link_set = NULL; /* for clean memory free */
  1056.     MarkedLinkSetFree (mls);
  1057.  
  1058.     return lsp;
  1059. }
  1060.  
  1061. LinkSetPtr CDECL NetUidLinks(DocType type, DocUid uid, DocType link_to_type)
  1062. {
  1063.     int i;
  1064.     LinkSetPtr retval;
  1065.     short erract;
  1066.     ErrDesc err;
  1067.  
  1068.     for (i = 0; i < ENT_SERV_RETRIES; i++)
  1069.     {
  1070.         if (i > 0)
  1071.         {
  1072.             if (! ReestablishNetEntrez())
  1073.                 break;
  1074.         }
  1075.  
  1076.         ErrGetOpts(&erract, NULL);
  1077.         ErrSetOpts(ERR_CONTINUE, 0);
  1078.         ErrFetch(&err);
  1079.         retval = s_NetUidLinks(type, uid, link_to_type);
  1080.         ErrSetOpts(erract, 0);
  1081.         if (! ErrFetch(&err))
  1082.             return retval; /* success */
  1083.     }
  1084.  
  1085.     ErrPost(CTX_UNKNOWN, 1, "NetUidLinks failure");
  1086.     return NULL;
  1087. }
  1088.  
  1089.  
  1090. /* The number of pages or terms to be obtain from the network in one request */
  1091. #define NUM_NET_PAGES       4
  1092. #define NUM_NET_TERMS       50
  1093.  
  1094. /* The maximum number of terms to obtain in one TermListByTerm; this value   */
  1095. /* need not depend upon NUM_NET_TERMS                                        */
  1096. #define OBTAIN_IN_ONE_READ 100
  1097.  
  1098. /*****************************************************************************
  1099. *
  1100. *   NetTermListByTerm (type, field, term, numterms, proc, first_page)
  1101. *       Gets Terms starting with page near term
  1102. *       returns number of complete pages read
  1103. *       sets first_page to first page read
  1104. *
  1105. *****************************************************************************/
  1106. static
  1107. Int2 NEAR s_NetTermListByTerm (DocType type, DocField field, CharPtr term,
  1108.                                  Int2 numterms, TermListProc proc,
  1109.                                  Int2Ptr first_page)
  1110.  
  1111. {
  1112.     AsnIoPtr asnin = Entrez_asnin;
  1113.     AsnIoPtr asnout = Entrez_asnout;
  1114.     int i;
  1115.     TermRespPtr p;
  1116.     TermByTermPtr tbt;
  1117.     TermByPagePtr tbp;
  1118.     AsnTypePtr atp;
  1119.     extern TermRespPtr TermRespAsnRead();
  1120.     struct termresp PNTR termp;
  1121.     int retval = 0;
  1122.     int first_read = TRUE;
  1123.     Boolean done = FALSE;
  1124.     int next_page;
  1125.     Int4 max_terms;
  1126.     int terms_to_read;
  1127.  
  1128.     if (numterms == 0) /* 0 ==> infinity */
  1129.         max_terms = INT4_MAX;
  1130.     else
  1131.         max_terms = numterms;
  1132.  
  1133.     while (! done) {
  1134.         terms_to_read = MIN(max_terms, NUM_NET_TERMS);
  1135.         if (first_read)
  1136.         {
  1137.             tbt = TermByTermNew();
  1138.     
  1139.             AsnWrite(Entrez_asnout, ENTREZ_REQUEST, NULL);
  1140.             tbt->type = type;
  1141.             tbt->fld = field;
  1142.             tbt->term = StringSave(term);
  1143.  
  1144.             /* For efficiency, if the caller has only requested a few terms, */
  1145.             /* then obtain them all in one shot; also note that if we're not */
  1146.             /* going to obtain all of the requested terms in a single shot,  */
  1147.             /* then num_terms must be 0, because we need to read an integral */
  1148.             /* number of pages.                                              */
  1149.             if (max_terms <= OBTAIN_IN_ONE_READ)
  1150.                 tbt->num_terms = max_terms;
  1151.             else
  1152.                 tbt->num_terms = 0; /* bounded by # of pages, not terms */
  1153.  
  1154.             TermByTermAsnWrite(tbt, Entrez_asnout, ENTREZ_REQUEST_byterm);
  1155.             TermByTermFree (tbt);
  1156.         }
  1157.         else { /* we already know what page */
  1158.             tbp = TermByPageNew();
  1159.     
  1160.             AsnWrite(Entrez_asnout, ENTREZ_REQUEST, NULL);
  1161.             tbp->type = type;
  1162.             tbp->fld = field;
  1163.             tbp->page = next_page;
  1164.             tbp->num_pages = NUM_NET_PAGES;
  1165.             TermByPageAsnWrite(tbp, Entrez_asnout, ENTREZ_REQUEST_bypage);
  1166.             TermByPageFree (tbp);
  1167.         }
  1168.  
  1169.         AsnIoReset(Entrez_asnout);
  1170.     
  1171.         /* now, read back response */
  1172.         if ((atp = NetEntReadAsn()) == NULL)
  1173.             return -1;
  1174.         if ((p = TermRespAsnRead(asnin, atp)) == NULL)
  1175.             return -1;
  1176.     
  1177.         if (first_read)
  1178.         {
  1179.             *first_page = p->first_page;
  1180.             next_page = p->first_page;
  1181.             first_read = FALSE;
  1182.         }
  1183.  
  1184.         if (p->num_terms == 0) /* end of file */
  1185.             done = TRUE;
  1186.  
  1187.         termp = p->termresp;
  1188.     
  1189.         LOG_STAT(SUBSYS_CLI_ENTREZ, "Terms read (by term)", p->num_terms);
  1190.         for (i = 0; i < p->num_terms && !done; i++, termp++)
  1191.         {
  1192.             /* StringSave() is needed because application frees the term */
  1193.             if (! proc(termp->term, termp->special_count, termp->total_count) )
  1194.                 done = TRUE;
  1195.             termp->term = NULL; 
  1196.         }
  1197.     
  1198.         retval += p->num_pages_read;
  1199.         max_terms -= p->num_terms;
  1200.         next_page += p->num_pages_read;
  1201.  
  1202.         TermRespFree (p);
  1203.  
  1204.         if (max_terms <= 0)
  1205.             done = TRUE;
  1206.     }
  1207.  
  1208.     LOG_STAT(SUBSYS_CLI_ENTREZ, "Term pages read (by term)", retval);
  1209.     return retval; /* page count */
  1210. }
  1211.  
  1212. Int2 CDECL NetTermListByTerm (DocType type, DocField field, CharPtr term,
  1213.                                Int2 numterms, TermListProc proc,
  1214.                                Int2Ptr first_page)
  1215. {
  1216.     int i;
  1217.     int retval;
  1218.     short erract;
  1219.     ErrDesc err;
  1220.  
  1221.     for (i = 0; i < ENT_SERV_RETRIES; i++)
  1222.     {
  1223.         if (i > 0)
  1224.         {
  1225.             if (! ReestablishNetEntrez())
  1226.                 break;
  1227.         }
  1228.  
  1229.         ErrGetOpts(&erract, NULL);
  1230.         ErrSetOpts(ERR_CONTINUE, 0);
  1231.         ErrFetch(&err);
  1232.         retval = s_NetTermListByTerm (type, field, term, numterms,
  1233.                                       proc, first_page);
  1234.         ErrSetOpts(erract, 0);
  1235.         if (! ErrFetch(&err))
  1236.             return retval; /* success */
  1237.     }
  1238.  
  1239.     ErrPost(CTX_UNKNOWN, 1, "NetTermListByTerm failure");
  1240.     return 0;
  1241. }
  1242.  
  1243. /*****************************************************************************
  1244. *
  1245. *   NetTermListByPage (type, field, page, numpage, proc)
  1246. *       Gets terms starting at page, for numpage, by calling proc
  1247. *       returns number of complete pages read
  1248. *
  1249. *****************************************************************************/
  1250.  
  1251. static
  1252. Int2 NEAR s_NetTermListByPage (DocType type, DocField field, Int2 page,
  1253.                                  Int2 numpage, TermListProc proc)
  1254.  
  1255. {
  1256.     AsnIoPtr asnin = Entrez_asnin;
  1257.     AsnIoPtr asnout = Entrez_asnout;
  1258.     TermRespPtr p;
  1259.     int i;
  1260.     struct termresp PNTR termp;
  1261.     TermByPagePtr tbp;
  1262.     AsnTypePtr atp;
  1263.     Boolean done = FALSE;
  1264.     int retval = 0;
  1265.     int next_page = page;
  1266.     int pages_to_read;
  1267.     Int4 max_pages;
  1268.  
  1269.     if (numpage == 0) /* 0 ==> infinity */
  1270.         max_pages = INT4_MAX;
  1271.     else
  1272.         max_pages = numpage;
  1273.  
  1274.     while (! done) {
  1275.         pages_to_read = MIN(max_pages, NUM_NET_PAGES);
  1276.         tbp = TermByPageNew();
  1277.     
  1278.         AsnWrite(Entrez_asnout, ENTREZ_REQUEST, NULL);
  1279.         tbp->type = type;
  1280.         tbp->fld = field;
  1281.         tbp->page = next_page;
  1282.         tbp->num_pages = pages_to_read;
  1283.         TermByPageAsnWrite(tbp, Entrez_asnout, ENTREZ_REQUEST_bypage);
  1284.         TermByPageFree(tbp);
  1285.         AsnIoReset(Entrez_asnout);
  1286.     
  1287.         /* now, read back response */
  1288.         if ((atp = NetEntReadAsn()) == NULL)
  1289.             return -1;
  1290.         if ((p = TermRespAsnRead(asnin, atp)) == NULL)
  1291.             return -1;
  1292.     
  1293.         if (p->num_terms == 0) /* end of file */
  1294.             done = TRUE;
  1295.  
  1296.         termp = p->termresp;
  1297.     
  1298.         LOG_STAT(SUBSYS_CLI_ENTREZ, "Terms read (by page)", p->num_terms);
  1299.         for (i = 0; i < p->num_terms && !done; i++, termp++)
  1300.         {
  1301.             /* StringSave() is needed because application frees the term */
  1302.             if (! proc(termp->term, termp->special_count, termp->total_count) )
  1303.                 done = TRUE;
  1304.             termp->term = NULL;
  1305.         }
  1306.     
  1307.         retval += p->num_pages_read;
  1308.         TermRespFree (p);
  1309.  
  1310.         next_page += pages_to_read;
  1311.         max_pages -= pages_to_read;
  1312.  
  1313.         if (max_pages <= 0)
  1314.             done = TRUE;
  1315.     }
  1316.     LOG_STAT(SUBSYS_CLI_ENTREZ, "Term pages read (by page)", retval);
  1317.     return retval; /* page count */
  1318. }
  1319.  
  1320. Int2 CDECL NetTermListByPage (DocType type, DocField field, Int2 page,
  1321.                                Int2 numpage, TermListProc proc)
  1322. {
  1323.     int i;
  1324.     int retval;
  1325.     short erract;
  1326.     ErrDesc err;
  1327.  
  1328.     for (i = 0; i < ENT_SERV_RETRIES; i++)
  1329.     {
  1330.         if (i > 0)
  1331.         {
  1332.             if (! ReestablishNetEntrez())
  1333.                 break;
  1334.         }
  1335.  
  1336.         ErrGetOpts(&erract, NULL);
  1337.         ErrSetOpts(ERR_CONTINUE, 0);
  1338.         ErrFetch(&err);
  1339.         retval = s_NetTermListByPage (type, field, page, numpage, proc);
  1340.         ErrSetOpts(erract, 0);
  1341.         if (! ErrFetch(&err))
  1342.             return retval; /* success */
  1343.     }
  1344.  
  1345.     ErrPost(CTX_UNKNOWN, 1, "NetTermListByPage failure");
  1346.     return 0;
  1347. }
  1348.  
  1349. /*****************************************************************************
  1350. *
  1351. *   NetEntrezFindTerm(type, field, term, spec, total)
  1352. *       returns count of special and total for a term
  1353. *       if term ends with  "...", does a truncated merge of the term
  1354. *
  1355. *****************************************************************************/
  1356. static
  1357. Boolean NEAR s_NetEntrezFindTerm (DocType type, DocField field, 
  1358.                                   CharPtr term, Int4Ptr spcl, Int4Ptr totl)
  1359.  
  1360. {
  1361.     AsnIoPtr asnin = Entrez_asnin;
  1362.     AsnIoPtr asnout = Entrez_asnout;
  1363.     TermCountsPtr tcs;
  1364.     TermLookupPtr tlp;
  1365.     Boolean found;
  1366.     AsnTypePtr atp;
  1367.     
  1368.     tlp = TermLookupNew();
  1369.     tlp->type = type;
  1370.     tlp->fld = field;
  1371.     tlp->term = StringSave(term);
  1372.     AsnWrite(asnout, ENTREZ_REQUEST, NULL);
  1373.     TermLookupAsnWrite(tlp, asnout, ENTREZ_REQUEST_findterm);
  1374.     TermLookupFree(tlp);
  1375.     AsnIoReset(asnout);
  1376.  
  1377.     /* now, read back response */
  1378.     if ((atp = NetEntReadAsn()) == NULL)
  1379.         return FALSE;
  1380.     if ((tcs = TermCountsAsnRead(asnin, atp)) == NULL)
  1381.         return FALSE;
  1382.     LOG_STAT(SUBSYS_CLI_ENTREZ, "Term lookup attempts", 1);
  1383.     LOG_STAT(SUBSYS_CLI_ENTREZ, "Terms found (special)", tcs->spec_count);
  1384.     LOG_STAT(SUBSYS_CLI_ENTREZ, "Terms found (total)", tcs->tot_count);
  1385.     *spcl = tcs->spec_count;
  1386.     *totl = tcs->tot_count;
  1387.     found = tcs->found;
  1388.  
  1389.     TermCountsFree(tcs);
  1390.  
  1391.     return found;
  1392. }
  1393.  
  1394. Boolean CDECL NetEntrezFindTerm (DocType type, DocField field,
  1395.                                  CharPtr term, Int4Ptr spcl, Int4Ptr totl)
  1396.  
  1397. {
  1398.     int i;
  1399.     int retval;
  1400.     short erract;
  1401.     ErrDesc err;
  1402.  
  1403.     for (i = 0; i < ENT_SERV_RETRIES; i++)
  1404.     {
  1405.         if (i > 0)
  1406.         {
  1407.             if (! ReestablishNetEntrez())
  1408.                 break;
  1409.         }
  1410.  
  1411.         ErrGetOpts(&erract, NULL);
  1412.         ErrSetOpts(ERR_CONTINUE, 0);
  1413.         ErrFetch(&err);
  1414.         retval = s_NetEntrezFindTerm (type, field, term, spcl, totl);
  1415.         ErrSetOpts(erract, 0);
  1416.         if (! ErrFetch(&err))
  1417.             return retval; /* success */
  1418.     }
  1419.  
  1420.     ErrPost(CTX_UNKNOWN, 1, "NetEntrezFindTerm failure");
  1421.     return FALSE;
  1422. }
  1423.  
  1424.  
  1425. static void CleanupNamedUidLists (void)
  1426. {
  1427.     ValNodePtr node;
  1428.     NamedItemPtr nip;
  1429.     ValNodePtr nextNode;
  1430.  
  1431.     for (node = namedTerms; node != NULL; node = nextNode)
  1432.     {
  1433.         nip = (NamedItemPtr) node->data.ptrvalue;
  1434.  
  1435.         nextNode = node->next;
  1436.  
  1437.         if (nip != NULL) {
  1438.             FileRemove (nip->tmpFileName);
  1439.             MemFree (nip->term);
  1440.             MemFree (nip);
  1441.         }
  1442.  
  1443.         MemFree (node);
  1444.     }
  1445.  
  1446.     namedTerms = NULL;
  1447. }
  1448.  
  1449. /**** Check to see if a term is already known to the Network server ********/
  1450. static NamedListPtr KnownNamedTerm (CharPtr term, Boolean onlyIfNotKnown,
  1451.                                     DocType type, DocField field)
  1452. {
  1453.     static NamedList dummy;
  1454.     ValNodePtr node;
  1455.     NamedItemPtr nip;
  1456.     AsnIoPtr aip;
  1457.     NamedListPtr nlp;
  1458.  
  1459.  
  1460.     for (node = namedTerms; node != NULL; node = node->next)
  1461.     {
  1462.         nip = (NamedItemPtr) node->data.ptrvalue;
  1463.  
  1464.         if (nip == NULL) {
  1465.             continue;
  1466.         }
  1467.  
  1468.         if (StringICmp (term, nip->term) == 0 && type == nip->type &&
  1469.             field == nip->field)
  1470.         { /* match */
  1471.             if (onlyIfNotKnown) {
  1472.                 if (! nip->knownToServer) {
  1473.                     /* read the file and load the data structure */
  1474.                     aip = AsnIoOpen (nip->tmpFileName, "rb");
  1475.                     nlp = NamedListAsnRead(aip, NULL);
  1476.                     AsnIoClose (aip);
  1477.                     return nlp;
  1478.                 } else {
  1479.                     return NULL;
  1480.                 }
  1481.             } else {
  1482.                 return &dummy;
  1483.             }
  1484.         }
  1485.     }
  1486.  
  1487.     return NULL; /* not found */
  1488. }
  1489.  
  1490. /**** Creates a term node from the uid parameter ********/
  1491. static void NEAR s_NetEntrezCreateNamedUidList (CharPtr term, DocType type, DocField field, Int4 num, DocUidPtr uids)
  1492. {
  1493.     AsnIoPtr asnin = Entrez_asnin;
  1494.     AsnIoPtr asnout = Entrez_asnout;
  1495.     NamedListPtr nlp;
  1496.     AsnTypePtr atp;
  1497.     NamedItemPtr namedItem;
  1498.     AsnIoPtr aip;
  1499.     ValNodePtr node;
  1500.  
  1501.     nlp = NamedListNew();
  1502.     nlp->type = type;
  1503.     nlp->fld = field;
  1504.     nlp->term = StringSave(term);
  1505.     nlp->uids = EntrezIdsNew();
  1506.     nlp->uids->numid = num;
  1507.     nlp->uids->ids = (DocUidPtr) MemDup(uids, (size_t) num * sizeof(DocUid));
  1508.     AsnWrite(asnout, ENTREZ_REQUEST, NULL);
  1509.     NamedListAsnWrite(nlp, asnout, ENTREZ_REQUEST_createnamed);
  1510.     
  1511.     AsnIoReset(asnout);
  1512.  
  1513.     if (KnownNamedTerm(term, FALSE, type, field) == NULL) {
  1514.         node = ValNodeNew (namedTerms);
  1515.         if (namedTerms == NULL) {
  1516.           namedTerms = node;
  1517.         }
  1518.         namedItem = MemNew (sizeof(NamedItem));
  1519.         if (node != NULL && namedItem != NULL) {
  1520.             namedItem->knownToServer = TRUE;
  1521.             TmpNam (namedItem->tmpFileName);
  1522.             namedItem->term = StringSave(term);
  1523.             namedItem->type = type;
  1524.             namedItem->field = field;
  1525.             node->data.ptrvalue = (VoidPtr) namedItem;
  1526.             aip = AsnIoOpen (namedItem->tmpFileName, "wb");
  1527.             NamedListAsnWrite (nlp, aip, NULL);
  1528.             AsnIoClose (aip);
  1529.         }
  1530.     }
  1531.  
  1532.     NamedListFree(nlp);
  1533.  
  1534.     if ((atp = NetEntReadAsn()) == NULL)
  1535.         return;
  1536.     if (AsnReadVal(asnin, atp, NULL) < 0)   /* read the NULL */
  1537.         return;
  1538.  
  1539.     LOG_STAT(SUBSYS_CLI_ENTREZ, "Named terms created", 1);
  1540.     LOG_STAT(SUBSYS_CLI_ENTREZ, "Named terms created (UID count)", num);
  1541. }
  1542.  
  1543. void CDECL NetEntrezCreateNamedUidListX (CharPtr term, DocType type, DocField field, ByteStorePtr bsp)
  1544. {}
  1545.  
  1546. void CDECL NetEntrezCreateNamedUidList (CharPtr term, DocType type, DocField field, Int4 num, DocUidPtr uids)
  1547. {
  1548.     int i;
  1549.     short erract;
  1550.     ErrDesc err;
  1551.  
  1552.     for (i = 0; i < ENT_SERV_RETRIES; i++)
  1553.     {
  1554.         if (i > 0)
  1555.         {
  1556.             if (! ReestablishNetEntrez())
  1557.                 break;
  1558.         }
  1559.  
  1560.         ErrGetOpts(&erract, NULL);
  1561.         ErrSetOpts(ERR_CONTINUE, 0);
  1562.         ErrFetch(&err);
  1563.         s_NetEntrezCreateNamedUidList (term, type, field, num, uids);
  1564.         ErrSetOpts(erract, 0);
  1565.         if (! ErrFetch(&err))
  1566.             return; /* success */
  1567.     }
  1568.  
  1569.     ErrPost(CTX_UNKNOWN, 1, "NetEntrezCreateNamedUidList failure");
  1570.     return;
  1571. }
  1572.  
  1573.  
  1574. static AsnTypePtr NetEntReadAsn(void)
  1575. {
  1576.     AsnTypePtr atp;
  1577.     DataVal av;
  1578.     AsnIoPtr asnin = Entrez_asnin;
  1579.     AsnModulePtr amp;
  1580.  
  1581.     NetEntAsnLoad();
  1582.     amp = AsnAllModPtr();
  1583.  
  1584.     atp = ENTREZ_BACK;
  1585.     if ((atp = AsnReadId(asnin, amp, atp)) != ENTREZ_BACK)
  1586.     {
  1587.         ErrPost(CTX_UNKNOWN, 1, "EOF on response from Entrez server");
  1588.         return NULL;
  1589.     }
  1590.     AsnReadVal(asnin, atp, &av);
  1591.     atp = AsnReadId(asnin, amp, atp);   /* read the CHOICE */
  1592.     if (atp == ENTREZ_BACK_error)
  1593.     {
  1594.         AsnReadVal(asnin, atp, &av);
  1595.         return NULL;
  1596.     }
  1597.     else
  1598.         return atp;
  1599. }
  1600.  
  1601. static Boolean ReestablishNetEntrez(void)
  1602. {
  1603.     Monitor *mon;
  1604.     Boolean retval;
  1605.     NamedItemPtr nip;
  1606.     ValNodePtr node;
  1607.     CharPtr uApplId = NULL;
  1608.  
  1609.     if (userApplId != NULL)
  1610.     { /* make a copy because this can get wiped out by NetEntrezInit() */
  1611.         uApplId = StringSave(userApplId); 
  1612.     }
  1613.  
  1614.     mon = MonitorStrNew("Re-establishing Entrez Service", 40);
  1615.     MonitorStrValue(mon, "Requesting Entrez service");
  1616.     NetFini();
  1617.     retval = TRUE;
  1618.  
  1619.     /* clear state information for named UID lists */
  1620.     for (node = namedTerms; node != NULL; node = node->next)
  1621.     {
  1622.         nip = (NamedItemPtr) node->data.ptrvalue;
  1623.  
  1624.         if (nip != NULL) {
  1625.             nip->knownToServer = FALSE;
  1626.         }
  1627.     }
  1628.  
  1629.     LOG_STAT(SUBSYS_CLI_ENTREZ, "Service Re-establishments", 1);
  1630.  
  1631.     if (! NetEntrezInit(uApplId, userWarnings))
  1632.     {
  1633.         MonitorStrValue(mon, "Entrez get failed; re-contacting dispatcher");
  1634.         retval = FALSE;
  1635.         if (ForceNetInit())
  1636.         { /* successfully established contact w/dispatcher */
  1637.             MonitorStrValue(mon, "Entrez get failed; re-requesting Entrez service");
  1638.             retval = NetEntrezInit(uApplId, userWarnings);
  1639.         }
  1640.         else {
  1641.             ErrPost(CTX_UNKNOWN, 1, "Unable to re-contact dispatcher");
  1642.             ErrShow();
  1643.             LOG_STAT(SUBSYS_CLI_ENTREZ, "Service Re-establishments \"retries\"", 1);
  1644.         }
  1645.     }
  1646.  
  1647.     MonitorFree(mon);
  1648.  
  1649.     if (! retval )
  1650.     {
  1651.         ErrPost(CTX_UNKNOWN, 1, "Unable to re-establish Entrez service");
  1652.         ErrShow();
  1653.     } else {
  1654.         ConfigFini(); /* to balance the extra ConfigInit() */
  1655.     }
  1656.  
  1657.     MemFree (uApplId);
  1658.     return retval;
  1659. }
  1660.  
  1661.  
  1662. static Boolean SwapInEntrez (VoidPtr med)
  1663. {
  1664.     MediaPtr media = (MediaPtr) med;
  1665.     NetMediaInfoPtr nmi;
  1666.  
  1667.     if (media == NULL || (nmi = (NetMediaInfoPtr) media->media_info) == NULL)
  1668.         return FALSE;
  1669.  
  1670.     if (nmi->sessionHandle == NULL)
  1671.         return FALSE;
  1672.  
  1673.     Entrez_ni = nmi->sessionHandle;
  1674.  
  1675.     Entrez_asnin = Entrez_ni->raip;
  1676.     Entrez_asnout = Entrez_ni->waip;
  1677.  
  1678.     return TRUE;
  1679. }
  1680.  
  1681. static void countChars(CharPtr str)
  1682. {
  1683.     charCount += StringLen(str) + 5;
  1684. }
  1685.  
  1686. /*****************************************************************************
  1687. *
  1688. *   NetEntMedlineEntryListGet (result, numuid, uids, mark_missing)
  1689. *       returns a count of entries read
  1690. *       if (mark_missing) ids which could not be located are made negative
  1691. *
  1692. *****************************************************************************/
  1693. static
  1694. Int2 NEAR s_NetEntMedlineEntryListGet (MedlineEntryPtr PNTR result, Int2 numuid,
  1695.                                     DocUidPtr uids, Boolean mark_missing)
  1696. {
  1697.     AsnTypePtr atp;
  1698.     EntrezDocGetPtr edgp;
  1699.     MedlineEntryListPtr mllp;
  1700.     int count;
  1701.  
  1702.     edgp = EntrezDocGetNew();
  1703.  
  1704.     edgp->cls = TYP_ML; /* unused */
  1705.     edgp->ids = EntrezIdsNew();
  1706.     edgp->ids->numid = numuid;
  1707.     edgp->ids->ids = uids;
  1708.     edgp->mark_missing = mark_missing;
  1709.  
  1710.     AsnWrite(Entrez_asnout, ENTREZ_REQUEST, NULL);
  1711.     EntrezDocGetAsnWrite(edgp, Entrez_asnout, ENTREZ_REQUEST_getmle);
  1712.     AsnIoReset(Entrez_asnout);
  1713.     edgp->ids->ids = NULL; /* for clean memory free */
  1714.     EntrezDocGetFree(edgp);
  1715.  
  1716.     if ((atp = NetEntReadAsn()) == NULL)
  1717.         return 0;
  1718.  
  1719.     mllp = MedlineEntryListAsnRead(Entrez_asnin, atp);
  1720.     MemCopy (result, mllp->data, (size_t) mllp->num * sizeof(MedlineEntryPtr));
  1721.  
  1722.     /* note that the structures underlying mllp->data are not freed; they */
  1723.     /* are used by the caller                                             */
  1724.     MemFree(mllp->data);
  1725.     mllp->data = NULL; /* for clean free */
  1726.     if (mark_missing && mllp->marked_missing)
  1727.     {
  1728.         MemCopy (uids, mllp->marked_missing->ids,
  1729.              (size_t) mllp->marked_missing->numid * sizeof(DocUid));
  1730.     }
  1731.     count = mllp->num;
  1732.     MedlineEntryListFree (mllp);
  1733.     LOG_STAT(SUBSYS_CLI_ENTREZ, "Medline entries retrieved", count);
  1734.     LOG_STAT(SUBSYS_CLI_ENTREZ, "Medline entries requested", numuid);
  1735.     
  1736.     return count;
  1737. }
  1738.  
  1739. Int2 NetEntMedlineEntryListGet (MedlineEntryPtr PNTR result, Int2 numuid,
  1740.                                     DocUidPtr uids, Boolean mark_missing)
  1741. {
  1742.     int i;
  1743.     int retval;
  1744.     short erract;
  1745.     ErrDesc err;
  1746.     DocUidPtr local_uids;
  1747.  
  1748.     /* make a local copy, to handle modifications */
  1749.     local_uids = MemNew(sizeof(DocUid) * numuid);
  1750.  
  1751.     for (i = 0; i < ENT_SERV_RETRIES; i++)
  1752.     {
  1753.         MemCopy(local_uids, uids, sizeof(DocUid) * numuid);
  1754.         if (i > 0)
  1755.         {
  1756.             if (! ReestablishNetEntrez())
  1757.                 break;
  1758.         }
  1759.  
  1760.         ErrGetOpts(&erract, NULL);
  1761.         ErrSetOpts(ERR_CONTINUE, 0);
  1762.         ErrFetch(&err);
  1763.         retval = s_NetEntMedlineEntryListGet(result, numuid, local_uids,
  1764.                                           mark_missing);
  1765.         ErrSetOpts(erract, 0);
  1766.         if (! ErrFetch(&err))
  1767.         {
  1768.             MemCopy(uids, local_uids, sizeof(DocUid) * numuid);
  1769.             MemFree(local_uids);
  1770.             return retval; /* success */
  1771.         }
  1772.     }
  1773.  
  1774.     MemFree(local_uids);
  1775.     ErrPost(CTX_UNKNOWN, 1, "NetMedlineEntryListGet failure");
  1776.     return -1;
  1777. }
  1778.  
  1779. /*****************************************************************************
  1780. *
  1781. *   NetEntSeqEntryListGet (result, numuid, uids, mark_missing)
  1782. *       returns a count of entries read
  1783. *       if (mark_missing) ids which could not be located are made negative
  1784. *
  1785. *****************************************************************************/
  1786. static
  1787. Int2 NEAR s_NetEntSeqEntryListGet (SeqEntryPtr PNTR result, Int2 numuid, DocUidPtr uids, Int2 retcode, Boolean mark_missing)
  1788. {
  1789.     AsnTypePtr atp;
  1790.     EntrezIdsPtr glp;
  1791.     SeqEntryListPtr selp;
  1792.     EntrezSeqGetPtr sgsp;
  1793.     int count;
  1794.  
  1795.     sgsp = EntrezSeqGetNew();
  1796.     glp = EntrezIdsNew();
  1797.     sgsp->ids = glp;
  1798.  
  1799.     glp->numid = numuid;
  1800.     glp->ids = uids;
  1801.     sgsp->mark_missing = mark_missing;
  1802.     sgsp->retype = retcode;
  1803.  
  1804. #if 1
  1805.     {
  1806.     // dgg test
  1807.     AsnIoPtr textout;
  1808.     textout= AsnIoOpen("entr-seqget.asn", "w");
  1809.     textout->type |= ASNIO_TEXT;
  1810.     AsnWrite(textout, ENTREZ_REQUEST, NULL);
  1811.     EntrezSeqGetAsnWrite(sgsp, textout, ENTREZ_REQUEST_getseq);
  1812.     AsnIoClose(textout);
  1813.     }
  1814. #endif
  1815.  
  1816.     AsnWrite(Entrez_asnout, ENTREZ_REQUEST, NULL);
  1817.     EntrezSeqGetAsnWrite(sgsp, Entrez_asnout, ENTREZ_REQUEST_getseq);
  1818.     AsnIoReset(Entrez_asnout);
  1819.     glp->ids = NULL; /* for clean memory free */
  1820.     EntrezSeqGetFree(sgsp);
  1821.  
  1822.     if ((atp = NetEntReadAsn()) == NULL)
  1823.         return 0;
  1824.  
  1825.     selp = SeqEntryListAsnRead(Entrez_asnin, atp);
  1826.     MemCopy (result, selp->data, (size_t) selp->num * sizeof(SeqEntryPtr));
  1827.     /* note that the structures underlying selp->data are not freed; they */
  1828.     /* are used by the caller                                             */
  1829.     MemFree(selp->data);
  1830.     selp->data = NULL; /* for clean free */
  1831.     if (mark_missing && selp->marked_missing)
  1832.     {
  1833.         MemCopy (uids, selp->marked_missing->ids,
  1834.              (size_t) selp->marked_missing->numid * sizeof(DocUid));
  1835.     }
  1836.     count = selp->num;
  1837.     SeqEntryListFree (selp);
  1838.     LOG_STAT(SUBSYS_CLI_ENTREZ, "Sequence entries retrieved", count);
  1839.     LOG_STAT(SUBSYS_CLI_ENTREZ, "Sequence entries requested", numuid);
  1840.     
  1841.     return count;
  1842. }
  1843.  
  1844. Int2 CDECL NetEntSeqEntryListGet (SeqEntryPtr PNTR result, Int2 numuid,
  1845.                                DocUidPtr uids, Int2 retcode, Boolean mark_missing)
  1846. {
  1847.     int i;
  1848.     int retval;
  1849.     short erract;
  1850.     ErrDesc err;
  1851.     DocUidPtr local_uids;
  1852.  
  1853.     /* make a local copy, to handle modifications */
  1854.     local_uids = MemNew(sizeof(DocUid) * numuid);
  1855.  
  1856.     for (i = 0; i < ENT_SERV_RETRIES; i++)
  1857.     {
  1858.         MemCopy(local_uids, uids, sizeof(DocUid) * numuid);
  1859.         if (i > 0)
  1860.         {
  1861.             if (! ReestablishNetEntrez())
  1862.                 break;
  1863.         }
  1864.  
  1865.         ErrGetOpts(&erract, NULL);
  1866.         ErrSetOpts(ERR_CONTINUE, 0);
  1867.         ErrFetch(&err);
  1868.         retval = s_NetEntSeqEntryListGet(result, numuid, local_uids, retcode,
  1869.                                       mark_missing);
  1870.         ErrSetOpts(erract, 0);
  1871.         if (! ErrFetch(&err))
  1872.         {
  1873.             MemCopy(uids, local_uids, sizeof(DocUid) * numuid);
  1874.             MemFree(local_uids);
  1875.             return retval; /* success */
  1876.         }
  1877.     }
  1878.  
  1879.     MemFree(local_uids);
  1880.     ErrPost(CTX_UNKNOWN, 1, "NetSeqEntryListGet failure");
  1881.     return -1;
  1882. }
  1883.  
  1884.  
  1885. #ifdef Biostruc_supported
  1886. /*****************************************************************************
  1887. *
  1888. *   NetEntrezBiostrucListGet (result, numuid, uids, mark_missing)
  1889. *       returns a count of entries read
  1890. *       if (mark_missing) ids which could not be located are made negative
  1891. *
  1892. *****************************************************************************/
  1893. static
  1894. Int2 NEAR s_NetEntrezBiostrucListGet (BiostrucPtr PNTR result, Int4 mdlLvl, Int2 numuid,
  1895.                                     DocUidPtr uids, Boolean mark_missing)
  1896. {
  1897.     AsnTypePtr atp;
  1898.     EntrezDocGetPtr edgp;
  1899.     BiostrucListPtr bslp;
  1900.     int count;
  1901.     DataVal av;
  1902.  
  1903.     edgp = EntrezDocGetNew();
  1904.  
  1905.     edgp->cls = TYP_ST; /* unused */
  1906.     edgp->ids = EntrezIdsNew();
  1907.     edgp->ids->numid = numuid;
  1908.     edgp->ids->ids = uids;
  1909.     edgp->mark_missing = mark_missing;
  1910.  
  1911.     av.intvalue = mdlLvl;
  1912.     AsnWrite(Entrez_asnout, ENTREZ_REQUEST, NULL);
  1913.     AsnStartStruct(Entrez_asnout, ENTREZ_REQUEST_getbiostrX);
  1914.     AsnWrite(Entrez_asnout, REQUEST_getbiostrX_complexity, &av);
  1915.     EntrezDocGetAsnWrite(edgp, Entrez_asnout, ENTREZ_REQUEST_getbiostrX_get);
  1916.     AsnEndStruct(Entrez_asnout, ENTREZ_REQUEST_getbiostrX);
  1917.     AsnIoReset(Entrez_asnout);
  1918.     edgp->ids->ids = NULL; /* for clean memory free */
  1919.     EntrezDocGetFree(edgp);
  1920.  
  1921.     if ((atp = NetEntReadAsn()) == NULL)
  1922.         return 0;
  1923.  
  1924.     bslp = BiostrucListAsnRead(Entrez_asnin, atp);
  1925.     MemCopy (result, bslp->data, (size_t) bslp->num * sizeof(BiostrucPtr));
  1926.  
  1927.     /* note that the structures underlying bslp->data are not freed; they */
  1928.     /* are used by the caller                                             */
  1929.     MemFree(bslp->data);
  1930.     bslp->data = NULL; /* for clean free */
  1931.     if (mark_missing && bslp->marked_missing)
  1932.     {
  1933.         MemCopy (uids, bslp->marked_missing->ids,
  1934.              (size_t) bslp->marked_missing->numid * sizeof(DocUid));
  1935.     }
  1936.     count = bslp->num;
  1937.     BiostrucListFree (bslp);
  1938.     LOG_STAT(SUBSYS_CLI_ENTREZ, "Biostruc entries retrieved", count);
  1939.     LOG_STAT(SUBSYS_CLI_ENTREZ, "Biostruc entries requested", numuid);
  1940.     
  1941.     return count;
  1942. }
  1943.  
  1944. Int2 NetEntrezBiostrucListGet (BiostrucPtr PNTR result, Int4 mdlLvl, Int2 numuid,
  1945.                                     DocUidPtr uids, Boolean mark_missing)
  1946. {
  1947.     int i;
  1948.     int retval;
  1949.     short erract;
  1950.     ErrDesc err;
  1951.     DocUidPtr local_uids;
  1952.  
  1953.     /* make a local copy, to handle modifications */
  1954.     local_uids = MemNew(sizeof(DocUid) * numuid);
  1955.  
  1956.     for (i = 0; i < ENT_SERV_RETRIES; i++)
  1957.     {
  1958.         MemCopy(local_uids, uids, sizeof(DocUid) * numuid);
  1959.         if (i > 0)
  1960.         {
  1961.             if (! ReestablishNetEntrez())
  1962.                 break;
  1963.         }
  1964.  
  1965.         ErrGetOpts(&erract, NULL);
  1966.         ErrSetOpts(ERR_CONTINUE, 0);
  1967.         ErrFetch(&err);
  1968.         retval = s_NetEntrezBiostrucListGet(result, mdlLvl, numuid, local_uids,
  1969.                                           mark_missing);
  1970.         ErrSetOpts(erract, 0);
  1971.         if (! ErrFetch(&err))
  1972.         {
  1973.             MemCopy(uids, local_uids, sizeof(DocUid) * numuid);
  1974.             MemFree(local_uids);
  1975.             return retval; /* success */
  1976.         }
  1977.     }
  1978.  
  1979.     MemFree(local_uids);
  1980.     ErrPost(CTX_UNKNOWN, 1, "NetBiostrucListGet failure");
  1981.     return -1;
  1982. }
  1983. #endif /* Biostruc_supported */
  1984.  
  1985.  
  1986. static
  1987. SeqIdPtr NEAR s_NetSeqIdForGI (DocUid gi)
  1988. {
  1989.     DataVal av;
  1990.     SeqIdPtr retval;
  1991.     AsnTypePtr atp;
  1992.  
  1993.     AsnWrite(Entrez_asnout, ENTREZ_REQUEST, NULL);
  1994.     av.intvalue = gi;
  1995.     AsnWrite(Entrez_asnout, ENTREZ_REQUEST_seqidforgi, &av);
  1996.     AsnIoReset(Entrez_asnout);
  1997.  
  1998.     if ((atp = NetEntReadAsn()) == NULL)
  1999.         return NULL;
  2000.  
  2001.     retval = SeqIdAsnRead(Entrez_asnin, atp);
  2002.  
  2003.     LOG_STAT(SUBSYS_CLI_ENTREZ, "Sequence IDs looked up by GI", 1);
  2004.  
  2005.     return retval;
  2006. }
  2007.  
  2008. SeqIdPtr CDECL NetSeqIdForGI (DocUid gi)
  2009. {
  2010.     int i;
  2011.     SeqIdPtr retval;
  2012.     short erract;
  2013.     ErrDesc err;
  2014.  
  2015.     for (i = 0; i < ENT_SERV_RETRIES; i++)
  2016.     {
  2017.         if (i > 0)
  2018.         {
  2019.             if (! ReestablishNetEntrez())
  2020.                 break;
  2021.         }
  2022.  
  2023.         ErrGetOpts(&erract, NULL);
  2024.         ErrSetOpts(ERR_CONTINUE, 0);
  2025.         ErrFetch(&err);
  2026.         retval = s_NetSeqIdForGI(gi);
  2027.         ErrSetOpts(erract, 0);
  2028.         if (! ErrFetch(&err))
  2029.         {
  2030.             return retval; /* success */
  2031.         }
  2032.     }
  2033.  
  2034.     ErrPost(CTX_UNKNOWN, 1, "NetSeqIdForGI failure");
  2035.     return NULL;
  2036. }
  2037.  
  2038. static
  2039. Int4 NEAR s_NetFindSeqId (SeqIdPtr sip)
  2040. {
  2041.     DataVal av;
  2042.     AsnTypePtr atp;
  2043.  
  2044.     AsnWrite(Entrez_asnout, ENTREZ_REQUEST, NULL);
  2045.     SeqIdAsnWrite(sip, Entrez_asnout, ENTREZ_REQUEST_findseqid);
  2046.     AsnIoReset(Entrez_asnout);
  2047.  
  2048.     if ((atp = NetEntReadAsn()) == NULL)
  2049.         return 0;
  2050.  
  2051.     AsnReadVal(Entrez_asnin, atp, &av);
  2052.  
  2053.     LOG_STAT(SUBSYS_CLI_ENTREZ, "Sequence GIs looked up by SeqID", 1);
  2054.  
  2055.     return av.intvalue;
  2056. }
  2057.  
  2058. Int4 CDECL NetEntrezFindSeqId (SeqIdPtr sip)
  2059. {
  2060.     int i;
  2061.     Int4 retval;
  2062.     short erract;
  2063.     ErrDesc err;
  2064.  
  2065.     for (i = 0; i < ENT_SERV_RETRIES; i++)
  2066.     {
  2067.         if (i > 0)
  2068.         {
  2069.             if (! ReestablishNetEntrez())
  2070.                 break;
  2071.         }
  2072.  
  2073.         ErrGetOpts(&erract, NULL);
  2074.         ErrSetOpts(ERR_CONTINUE, 0);
  2075.         ErrFetch(&err);
  2076.         retval = s_NetFindSeqId(sip);
  2077.         ErrSetOpts(erract, 0);
  2078.         if (! ErrFetch(&err))
  2079.         {
  2080.             return retval; /* success */
  2081.         }
  2082.     }
  2083.  
  2084.     ErrPost(CTX_UNKNOWN, 1, "NetFindSeqId failure");
  2085.  
  2086.     return 0;
  2087. }
  2088.  
  2089. static EntrezHierarchyPtr s_NetEntMeshHierarchyGet(CharPtr term)
  2090. {
  2091.   AsnIoPtr asnin = Entrez_asnin;
  2092.   AsnIoPtr asnout = Entrez_asnout;
  2093.   EntrezHierarchyPtr ehp;
  2094.   TermCountsPtr tcs;
  2095.   TermLookupPtr tlp;
  2096.   Boolean found;
  2097.   AsnTypePtr atp;
  2098.     
  2099.   tlp = TermLookupNew();
  2100.   tlp->type = TYP_ML;
  2101.   tlp->fld = FLD_MESH;
  2102.   tlp->term = StringSave(term);
  2103.   AsnWrite(asnout, ENTREZ_REQUEST, NULL);
  2104.   TermLookupAsnWrite(tlp, asnout, ENTREZ_REQUEST_get_hierarchy);
  2105.   TermLookupFree(tlp);
  2106.   AsnIoReset(asnout);
  2107.  
  2108.   /* now, read back response */
  2109.   if ((atp = NetEntReadAsn()) == NULL)
  2110.     return FALSE;
  2111.  
  2112.   if ( (ehp = EntrezHierarchyAsnRead(asnin,ENTREZ_BACK_get_hierarchy)) == NULL)
  2113.     return  NULL;
  2114.  
  2115.   if (ehp->numInLineage == 0 && ehp->numChildren == 0)
  2116.   {
  2117.       EntrezHierarchyFree(ehp);
  2118.       return NULL;
  2119.   }
  2120.  
  2121.   return (ehp);
  2122. }
  2123.  
  2124.  
  2125. EntrezHierarchyPtr NetEntMeshHierarchyGet(CharPtr term)
  2126. {
  2127.   int i;
  2128.   EntrezHierarchyPtr ehp;
  2129.   short erract;
  2130.   ErrDesc err;
  2131.   
  2132.   for (i = 0; i < ENT_SERV_RETRIES; i++)
  2133.     {
  2134.       if (i > 0)
  2135.         {
  2136.           if (! ReestablishNetEntrez())
  2137.             break;
  2138.         }
  2139.       
  2140.       ErrGetOpts(&erract, NULL);
  2141.       ErrSetOpts(ERR_CONTINUE, 0);
  2142.       ErrFetch(&err);
  2143.       ehp = s_NetEntMeshHierarchyGet(term);
  2144.       ErrSetOpts(erract, 0);
  2145.       if (! ErrFetch(&err))
  2146.         {
  2147.           return ehp; /* success */
  2148.         }
  2149.     }
  2150.   
  2151.   ErrPost(CTX_UNKNOWN, 1, "NetEntMeshTreeGet failure");
  2152.   
  2153.   return NULL;
  2154. }
  2155.  
  2156.  
  2157. static LinkSetPtr s_NetEntDoNeighborText(EntrezNeighborTextPtr entp)
  2158. {
  2159.   CharPtr normalTextPtr, specialTextPtr;
  2160.   LinkSetPtr lsp = NULL;
  2161.   AsnTypePtr atp;
  2162.   AsnIoPtr asnin = Entrez_asnin;
  2163.   AsnIoPtr asnout = Entrez_asnout;
  2164.  
  2165.   RemoveNonPrintingCharacters(entp->normalText);
  2166.   RemoveNonPrintingCharacters(entp->specialText);
  2167.  
  2168.   if  ( (*SkipSpaces(entp->normalText) == '\0')
  2169.        && (*SkipSpaces(entp->specialText) == '\0') )
  2170.     return (NULL);
  2171.  
  2172.   AsnWrite(asnout, ENTREZ_REQUEST, NULL);
  2173.   EntrezNeighborTextAsnWrite(entp,asnout,ENTREZ_REQUEST_neighbortext);
  2174.   AsnIoReset(asnout);
  2175.  
  2176.   if ( (atp = NetEntReadAsn()) == NULL)
  2177.     return NULL;
  2178.  
  2179.   if ( (lsp = LinkSetAsnRead(asnin, ENTREZ_BACK_neighbortext)) == NULL)
  2180.     return(NULL);
  2181.  
  2182.   return (lsp);
  2183. }
  2184.  
  2185.  
  2186.  
  2187. LinkSetPtr CDECL NetEntDoNeighborText (EntrezNeighborTextPtr entp)
  2188. {
  2189.   int i;
  2190.   LinkSetPtr lsp;
  2191.   short erract;
  2192.   ErrDesc err;
  2193.   
  2194.   for (i = 0; i < ENT_SERV_RETRIES; i++)
  2195.     {
  2196.       if (i > 0)
  2197.         {
  2198.           if (! ReestablishNetEntrez())
  2199.             break;
  2200.         }
  2201.       
  2202.       ErrGetOpts(&erract, NULL);
  2203.       ErrSetOpts(ERR_CONTINUE, 0);
  2204.       ErrFetch(&err);
  2205.       lsp = s_NetEntDoNeighborText(entp);
  2206. /* debug       if (lsp == NULL)
  2207.         fprintf(stderr,"failed to get linkset pointer. \n"); */
  2208.       ErrSetOpts(erract, 0);
  2209.       if (! ErrFetch(&err))
  2210.         return lsp; /* success */
  2211.     }
  2212.   
  2213.   ErrPost(CTX_UNKNOWN, 1, "NetEntDoNeighborText failure");
  2214.   return NULL;
  2215. }
  2216.  
  2217.  
  2218. Boolean CDECL NetEntCanNeighborText()
  2219. {
  2220.     EntrezExtraInfoPtr myeeip;
  2221.  
  2222.     if ((myeeip = GetEntrezExtraInfo()) == NULL)
  2223.     {
  2224.         return FALSE;
  2225.     }
  2226.  
  2227.     return myeeip->canneighbortext;
  2228. }
  2229.  
  2230.  
  2231. Boolean CDECL NetEntExpandedMedlineFeatures(void)
  2232. {
  2233.     EntrezExtraInfoPtr myeeip;
  2234.  
  2235.     if ((myeeip = GetEntrezExtraInfo()) == NULL)
  2236.     {
  2237.         return FALSE;
  2238.     }
  2239.  
  2240.     return myeeip->expanded_medline;
  2241. }
  2242.  
  2243.  
  2244. Boolean CDECL NetEntCanBlast()
  2245. {
  2246.     EntrezExtraInfoPtr myeeip;
  2247.  
  2248.     if ((myeeip = GetEntrezExtraInfo()) == NULL)
  2249.     {
  2250.         return FALSE;
  2251.     }
  2252.  
  2253.     return myeeip->canblast;
  2254. }
  2255.  
  2256.  
  2257. static void RemoveNonPrintingCharacters(CharPtr str)
  2258. {
  2259.   while (*str)
  2260.     {
  2261.       if ( (*str < ' ') || (*str > 0x7E) )
  2262.         *str = ' ';
  2263.       str++;
  2264.     }
  2265. }
  2266.  
  2267. static CharPtr SkipSpaces(CharPtr str)
  2268. {
  2269.   while (*str && (*str == ' '))
  2270.     str++;
  2271.   
  2272.   return str;
  2273. }
  2274.  
  2275. static Boolean
  2276. blastProgressMonitor (Int4 value, Boolean isStart, Boolean destroyIt)
  2277. {
  2278.     static MonitorPtr mon = NULL;
  2279.     Boolean retval = TRUE;
  2280.  
  2281.     if (destroyIt)
  2282.     {
  2283.         if (mon != NULL)
  2284.         {
  2285.             MonitorFree(mon);
  2286.             mon = NULL;
  2287.         }
  2288.         return TRUE;
  2289.     }
  2290.  
  2291.     if (isStart)
  2292.     {
  2293.         if (mon != NULL)
  2294.         {
  2295.             MonitorFree(mon);
  2296.             mon = NULL;
  2297.         }
  2298.         mon = MonitorIntNew("BLAST progress", 0, value);
  2299.     } else {
  2300.         if (mon != NULL)
  2301.         {
  2302.             retval = MonitorIntValue(mon, value);
  2303.         }
  2304.     }
  2305.  
  2306.     return retval;
  2307. }
  2308.  
  2309. static LinkSetPtr
  2310. s_NetEntBlastBioseq(BioseqPtr bsp, DocType db, CharPtr program, CharPtr database, CharPtr options, Boolean usemonitor, BoolPtr noMoreTriesPtr)
  2311. {
  2312.      EntrezBlastreqPtr ebrp;
  2313.      LinkSetPtr lsp;
  2314.      AsnTypePtr atp;
  2315.      DataVal av;
  2316.      AsnModulePtr amp;
  2317.  
  2318.      NetEntAsnLoad();
  2319.      amp = AsnAllModPtr();
  2320.  
  2321.      ebrp = EntrezBlastreqNew();
  2322.      ebrp->bsp = bsp;
  2323.      ebrp->bsp_database = db;
  2324.      ebrp->program = StringSave(program);
  2325.      ebrp->database = StringSave(database);
  2326.      ebrp->options = StringSave(options);
  2327.      ebrp->showprogress = usemonitor;
  2328.      EntrezBlastreqAsnWrite(ebrp, Entrez_asnout, ENTREZ_REQUEST_blast);
  2329.      ebrp->bsp = NULL; /* we don't "own" this so have no business freeing it */
  2330.      EntrezBlastreqFree(ebrp);
  2331.      AsnIoReset(Entrez_asnout);
  2332.  
  2333.      while (TRUE)
  2334.      {
  2335.          if ( (atp = NetEntReadAsn()) == NULL)
  2336.            return NULL;
  2337.          AsnReadVal(Entrez_asnin, atp, NULL);
  2338.          if ( (atp = AsnReadId(Entrez_asnin, amp, atp)) == NULL)
  2339.            return NULL;
  2340.          if (atp == ENTREZ_BACK_blast_bad_count)
  2341.          {
  2342.              blastProgressMonitor(0, FALSE, TRUE);
  2343.              return NULL;
  2344.          } else
  2345.          if (atp == ENTREZ_BACK_blast_link_set)
  2346.          {
  2347.              blastProgressMonitor(0, FALSE, TRUE);
  2348.              lsp = LinkSetAsnRead(Entrez_asnin, atp);
  2349.              return (lsp);
  2350.          } else
  2351.          if (atp == ENTREZ_BACK_blast_job_start)
  2352.          {
  2353.             AsnReadVal(Entrez_asnin, atp, &av);
  2354.             if (usemonitor)
  2355.                 blastProgressMonitor(av.intvalue, TRUE, FALSE);
  2356.          } else
  2357.          if (atp == ENTREZ_BACK_blast_job_progress)
  2358.          {
  2359.             AsnReadVal(Entrez_asnin, atp, &av);
  2360.             if (usemonitor)
  2361.                 if (! blastProgressMonitor(av.intvalue, FALSE, FALSE))
  2362.                 { /* user cancelled BLAST search */
  2363.                     blastProgressMonitor(0, FALSE, TRUE);
  2364.                     /* drop our connection since we don't know what state we're in */
  2365.                     ReestablishNetEntrez();
  2366.                     if (noMoreTriesPtr != NULL)
  2367.                         *noMoreTriesPtr = TRUE;
  2368.                     return NULL;
  2369.                 }
  2370.          } else {
  2371.              return NULL;
  2372.          }
  2373.      }
  2374. }
  2375.  
  2376. LinkSetPtr LIBCALL
  2377. NetEntBlastBioseq(BioseqPtr bsp, DocType db, CharPtr program, CharPtr database, CharPtr options, Boolean usemonitor)
  2378. {
  2379.   int i;
  2380.   LinkSetPtr lsp;
  2381.   short erract;
  2382.   ErrDesc err;
  2383.   Boolean noMoreTries;
  2384.   extern void MsgSetReadTimeout PROTO((MHandPtr mh, int t));
  2385.   
  2386.   for (i = 0; i < ENT_SERV_RETRIES; i++)
  2387.     {
  2388.       if (i > 0)
  2389.         {
  2390.           if (! ReestablishNetEntrez())
  2391.             break;
  2392.         }
  2393.       
  2394.       ErrGetOpts(&erract, NULL);
  2395.       ErrSetOpts(ERR_CONTINUE, 0);
  2396.       ErrFetch(&err);
  2397.       MsgSetReadTimeout(Entrez_ni, 1200);
  2398.       noMoreTries = FALSE;
  2399.       lsp = s_NetEntBlastBioseq(bsp, db, program, database, options, usemonitor, &noMoreTries);
  2400.       MsgSetReadTimeout(Entrez_ni, 60);
  2401.       ErrSetOpts(erract, 0);
  2402.       if (noMoreTries || ! ErrFetch(&err))
  2403.         return lsp;
  2404.     }
  2405.  
  2406.   ErrPost(CTX_UNKNOWN, 1, "NetEntBlastBioseq failure");
  2407.   return NULL;
  2408. }
  2409.   
  2410.  
  2411.